diff --git a/CHANGELOG.md b/CHANGELOG.md index 77ba534ab..15ce1b191 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,9 @@ mimpid = 0x01080200 => Version 01.08.02.00 => v1.8.2 | Date (*dd.mm.yyyy*) | Version | Comment | |:-------------------:|:-------:|:--------| +| 16.07.2023 | 1.8.6.5 | :warning: **rework SoC bus system & memory map - part 3**: re-enforce PMAs (physical memory attributes); [#648](https://github.com/stnolting/neorv32/pull/648) | +| 15.07.2023 | 1.8.6.4 | :warning: **rework SoC bus system & memory map - part 2**: move IO address decoding to central IO switch; add i-cache uncached accesses; [#648](https://github.com/stnolting/neorv32/pull/648) | +| 14.07.2023 | 1.8.6.3 | :warning: **rework SoC bus system & memory map - part 1**: add central bus gateway to control core accesses to the main address regions; [#648](https://github.com/stnolting/neorv32/pull/648) | | 14.07.2023 | 1.8.6.2 | minor rtl edits; [#646](https://github.com/stnolting/neorv32/pull/646) | | 30.06.2023 | 1.8.6.1 | minor rtl edits, cleanups and optimizations; [#641](https://github.com/stnolting/neorv32/pull/641) | | 27.06.2023 | [**:rocket:1.8.6**](https://github.com/stnolting/neorv32/releases/tag/v1.8.6) | **New release** | diff --git a/README.md b/README.md index d8a35de18..f05a5dba2 100644 --- a/README.md +++ b/README.md @@ -129,11 +129,10 @@ see the [_open-source architecture ID list_](https://github.com/riscv/riscv-isa- *Unprivileged ISA Specification* ([pdf](https://github.com/stnolting/neorv32/blob/main/docs/references/riscv-spec.pdf)) and *Privileged Architecture Specification* ([pdf](https://github.com/stnolting/neorv32/blob/main/docs/references/riscv-privileged.pdf)). * `machine` and `user` privilege modes -* implements **all** standard RISC-V exceptions and interrupts (including MTI, MEI & MSI) -* 16 fast interrupt request channels as NEORV32-specific extension +* implements **all** standard RISC-V exceptions and interrupts + 16 fast interrupt request channels as NEORV32-specific extension * custom functions unit ([CFU](https://stnolting.github.io/neorv32/#_custom_functions_unit_cfu) as `Zxcfu` ISA extension) for _custom RISC-V instructions_ (R3-type, R4-type and R5-type); -* _intrinsic_ libraries for the `Zicond`, `Zfinx` and `Zxcfu` ISA extensions +* _intrinsic_ libraries for CPU extensions that are not yet supported by GCC **Memories** @@ -176,13 +175,13 @@ allows booting application code via UART or from external SPI flash * **true** random number generator ([TRNG](https://stnolting.github.io/neorv32/#_true_random_number_generator_trng)) based on the [neoTRNG](https://github.com/stnolting/neoTRNG) -* execute-in-place module ([XIP](https://stnolting.github.io/neorv32/#_execute_in_place_module_xip)) to execute code directly from SPI flash +* execute-in-place module ([XIP](https://stnolting.github.io/neorv32/#_execute_in_place_module_xip)) to execute code right from a SPI flash * custom functions subsystem ([CFS](https://stnolting.github.io/neorv32/#_custom_functions_subsystem_cfs)) for custom tightly-coupled co-processors, accelerators or interfaces * direct memory access controller ([DMA](https://stnolting.github.io/neorv32/#_direct_memory_access_controller_dma)) for CPU-independent data transfers and conversions * cyclic redundancy check unit ([DMA](https://stnolting.github.io/neorv32/#_cyclic_redundancy_check_crc)) to test -data integrity (CRC8/CRC16/CRC32) +data integrity (CRC8/16/32) **Debugging** @@ -278,7 +277,7 @@ This overview provides some *quick links* to the most important sections of the * **[NEORV32 Project](https://stnolting.github.io/neorv32/#_overview) - introduction** * [Rationale](https://stnolting.github.io/neorv32/#_rationale) - why? how come? what for? * [Key Features](https://stnolting.github.io/neorv32/#_project_key_features) - what makes it special - * [Structure](https://stnolting.github.io/neorv32/#_project_folder_structure) - folders and RTL files + * [Structure](https://stnolting.github.io/neorv32/#_project_folder_structure) - folders, RTL files and compile order * [Metrics](https://stnolting.github.io/neorv32/#_fpga_implementation_results) - FPGA implementation and performance evaluation ### :electric_plug: Hardware Overview diff --git a/docs/datasheet/cpu.adoc b/docs/datasheet/cpu.adoc index 3cbf98403..e5338e7de 100644 --- a/docs/datasheet/cpu.adoc +++ b/docs/datasheet/cpu.adoc @@ -69,7 +69,7 @@ overlapping operation of fetch and execute) at a reduced hardware footprint (due As a Von-Neumann machine, the CPU provides independent interfaces for instruction fetch and data access. However, these two bus interfaces are merged into a single processor-internal bus via a prioritizing bus switch (data accesses have higher priority). Hence, _all_ memory addresses including peripheral devices are mapped to a single unified 32-bit -address space (see section <<_cpu_data_and_instruction_access>>). +<<_address_space>>. [NOTE] The CPU does not perform any speculative/out-of-order operations at all. Hence, it is not vulnerable to security issues @@ -821,9 +821,9 @@ The processor-internal modules do not have to respond within a fixed cycle amoun However, the bus transaction has to be completed (= acknowledged) within a certain **response time window**. This time window is defined by the global `max_proc_int_response_time_c` constant (default = 15 cycles; the processor's VHDL package file `rtl/neorv32_package.vhd`). It defines the maximum number of cycles after which a non-responding bus request (i.e. no `ack` -and no `*err` signal) will **time out** and will raise a bus access fault exception. The <<_internal_bus_monitor_buskeeper>> +and no `*err` signal) will **time out** and will raise a bus access fault exception. The memory GATEWAY keeps track of all bus transactions to enforce this time window. If any bus operations times out - for example when -accessing "address space holes" - the BUSKEEPER will issue a bus error to the CPU that will raise the according bus +accessing "address space holes" - the GATEWAY will issue a bus error to the CPU that will raise the according bus exception. .Access Boundaries diff --git a/docs/datasheet/on_chip_debugger.adoc b/docs/datasheet/on_chip_debugger.adoc index 29299adbc..b76bc2195 100644 --- a/docs/datasheet/on_chip_debugger.adoc +++ b/docs/datasheet/on_chip_debugger.adoc @@ -414,14 +414,14 @@ the _program buffer_, the _data buffer_ and the _status register_. The program b status register do not fully occupy the 64-byte-wide sections and are mirrored to fill the entire section. .DM CPU access - address map (divided into four sections) -[cols="^2,^4,^2,<7"] +[cols="^2,^2,<5"] [options="header",grid="rows"] |======================= -| Base address | Name [VHDL package] | Actual size | Description -| `0xfffff800` | `dm_code_base_c` (= `dm_base_c`) | 64 bytes | ROM for the "park loop" code -| `0xfffff840` | `dm_pbuf_base_c` | 16 bytes | Program buffer, provided by DM -| `0xfffff880` | `dm_data_base_c` | 4 bytes | Data buffer (`dm.data0`) -| `0xfffff8c0` | `dm_sreg_base_c` | 4 bytes | Control and status register +| Base address | Actual size | Description +| `0xffffff00` | 64 bytes | ROM for the "park loop" code +| `0xffffff40` | 16 bytes | Program buffer, provided by DM +| `0xffffff80` | 4 bytes | Data buffer (`dm.data0`) +| `0xffffffc0` | 4 bytes | Control and status register |======================= .DM Register Access diff --git a/docs/datasheet/overview.adoc b/docs/datasheet/overview.adoc index d84f25aa7..5a3e82206 100644 --- a/docs/datasheet/overview.adoc +++ b/docs/datasheet/overview.adoc @@ -128,36 +128,36 @@ of the user guide. === Project Folder Structure ................................... -neorv32 - Project home folder +neorv32 - Project home folder │ -├docs - Project documentation -│├datasheet - AsciiDoc sources for the NEORV32 data sheet -│├figures - Figures and logos -│├icons - Misc. symbols -│├references - Data sheets and RISC-V specs. -│└userguide - AsciiDoc sources for the NEORV32 user guide +├-docs - Project documentation +│ ├-datasheet - AsciiDoc sources for the NEORV32 data sheet +│ ├-figures - Figures and logos +│ ├-icons - Misc. symbols +│ ├-references - Data sheets and RISC-V specs. +│ └-userguide - AsciiDoc sources for the NEORV32 user guide │ -├rtl - VHDL sources -│├core - Core sources of the CPU & SoC -││└mem - SoC-internal memories (default architectures) -│├processor_templates - Pre-configured SoC wrappers -│├system_integration - System wrappers for advanced connectivity -│└test_setups - Minimal test setup "SoCs" used in the User Guide +├-rtl - VHDL sources +│ ├-core - Core sources of the CPU & SoC +│ │ └-mem - SoC-internal memories (default architectures) +│ ├-processor_templates - Pre-configured SoC wrappers +│ ├-system_integration - System wrappers for advanced connectivity +│ └-test_setups - Minimal test setup "SoCs" used in the User Guide │ -├sim - Simulation files (see User Guide) +├-sim - Simulation files (see User Guide) │ -└sw - Software framework - ├bootloader - Sources of the processor-internal bootloader - ├common - Linker script, crt0.S start-up code and central makefile - ├example - Example programs for the core and the SoC modules - │└... - ├lib - Processor core library - │├include - Header files (*.h) - │└source - Source files (*.c) - ├image_gen - Helper program to generate NEORV32 executables - ├ocd_firmware - Firmware for the on-chip debugger's "park loop" - ├openocd - OpenOCD configuration files - └svd - Processor system view description file (CMSIS-SVD) +└-sw - Software framework + ├-bootloader - Sources of the processor-internal bootloader + ├-common - Linker script, crt0.S start-up code and central makefile + ├-example - Example programs for the core and the SoC modules + │ └-... + ├-lib - Processor core library + │ ├-include - Header files (*.h) + │ └-source - Source files (*.c) + ├-image_gen - Helper program to generate NEORV32 executables + ├-ocd_firmware - Firmware for the on-chip debugger's "park loop" + ├-openocd - OpenOCD configuration files + └-svd - Processor system view description file (CMSIS-SVD) ................................... @@ -170,63 +170,70 @@ neorv32 - Project home folder All necessary VHDL hardware description files are located in the project's `rtl/core` folder. The top entity of the entire processor including all the required configuration generics is `neorv32_top.vhd`. -.NEORV32 VHDL Library +.Compile Order +[IMPORTANT] +Most of the RTL sources use **entity instantiation**. Hence, the RTL compile order might be relevant. +The list below shows the hierarchical compile order srarting at the top. + +.VHDL Library [IMPORTANT] All core VHDL files from the list below have to be assigned to a new design library named `neorv32`. ................................... -neorv32_top.vhd - NEORV32 Processor top entity + +┌-neorv32_package.vhd - Processor/CPU main VHDL package file +├-neorv32_fifo.vhd - Generic FIFO component +│ +│ ┌-neorv32_cpu_cp_bitmanip.vhd - Bit-manipulation co-processor (B ext.) +│ ├-neorv32_cpu_cp_cfu.vhd - Custom instructions co-processor (Zxcfu ext.) +│ ├-neorv32_cpu_cp_cond.vhd - Conditional operations co-processor (Zicond ext.) +│ ├-neorv32_cpu_cp_fpu.vhd - Floating-point co-processor (Zfinx ext.) +│ ├-neorv32_cpu_cp_shifter.vhd - Bit-shift co-processor (base ISA) +│ ├-neorv32_cpu_cp_muldiv.vhd - Mul/Div co-processor (M ext.) +│ ┌-neorv32_cpu_alu.vhd - Arithmetic/logic unit +│ ├-neorv32_cpu_bus.vhd - Load/store unit + physical memory protection +│ │ ┌-neorv32_cpu_decompressor.vhd - Compressed instructions decoder +│ ├-neorv32_cpu_control.vhd - CPU control, exception system and CSRs +│ ├-neorv32_cpu_regfile.vhd - Data register file +├-neorv32_cpu.vhd - NEORV32 CPU top entity +│ +├-mem/neorv32_dmem.default.vhd - _Default_ data memory (architecture-only) +├-mem/neorv32_imem.default.vhd - _Default_ instruction memory (architecture-only) │ -├neorv32_fifo.vhd - General purpose FIFO component -├neorv32_package.vhd - Processor/CPU main VHDL package file +│ ┌-neorv32_bootloader_image.vhd - Bootloader ROM memory image +├-neorv32_boot_rom.vhd - Bootloader ROM │ -├neorv32_cpu.vhd - NEORV32 CPU top entity -│├neorv32_cpu_alu.vhd - Arithmetic/logic unit -││├neorv32_cpu_cp_bitmanip.vhd - Bit-manipulation co-processor (B ext.) -││├neorv32_cpu_cp_cfu.vhd - Custom instructions co-processor (Zxcfu ext.) -││├neorv32_cpu_cp_cond.vhd - Conditional operations co-processor (Zicond ext.) -││├neorv32_cpu_cp_fpu.vhd - Floating-point co-processor (Zfinx ext.) -││├neorv32_cpu_cp_muldiv.vhd - Mul/Div co-processor (M ext.) -││└neorv32_cpu_cp_shifter.vhd - Bit-shift co-processor (base ISA) -│├neorv32_cpu_bus.vhd - Load/store unit + physical memory protection -│├neorv32_cpu_control.vhd - CPU control, exception system and CSRs -││└neorv32_cpu_decompressor.vhd - Compressed instructions decoder -│└neorv32_cpu_regfile.vhd - Data register file +│ ┌-neor32_application_image.vhd - IMEM application initialization image +├-neorv32_imem.entity.vhd - Processor-internal instruction memory (entity-only!) │ -├neorv32_boot_rom.vhd - Bootloader ROM -│└neorv32_bootloader_image.vhd - Bootloader ROM memory image -├neorv32_busswitch.vhd - Processor bus switch for CPU buses (I&D) -├neorv32_bus_keeper.vhd - Processor-internal bus monitor -├neorv32_cfs.vhd - Custom functions subsystem -├neorv32_crc.vhd - Cyclic redundancy check unit -├neorv32_dcache.vhd - Processor-internal data cache -├neorv32_debug_dm.vhd - on-chip debugger: debug module -├neorv32_debug_dtm.vhd - on-chip debugger: debug transfer module -├neorv32_dma.vhd - Direct memory access controller -├neorv32_dmem.entity.vhd - Processor-internal data memory (entity-only!) -├neorv32_gpio.vhd - General purpose input/output port unit -├neorv32_gptmr.vhd - General purpose 32-bit timer -├neorv32_icache.vhd - Processor-internal instruction cache -├neorv32_imem.entity.vhd - Processor-internal instruction memory (entity-only!) -│└neor32_application_image.vhd - IMEM application initialization image -├neorv32_mtime.vhd - Machine system timer -├neorv32_neoled.vhd - NeoPixel (TM) compatible smart LED interface -├neorv32_onewire.vhd - One-Wire serial interface controller -├neorv32_pwm.vhd - Pulse-width modulation controller -├neorv32_sdi.vhd - Serial data interface controller (SPI device) -├neorv32_slink.vhd - Stream link interface -├neorv32_spi.vhd - Serial peripheral interface controller (SPI host) -├neorv32_sysinfo.vhd - System configuration information memory -├neorv32_trng.vhd - True random number generator -├neorv32_twi.vhd - Two wire serial interface controller -├neorv32_uart.vhd - Universal async. receiver/transmitter -├neorv32_wdt.vhd - Watchdog timer -├neorv32_wishbone.vhd - External (Wishbone) bus interface -├neorv32_xip.vhd - Execute in place module -├neorv32_xirq.vhd - External interrupt controller +├neorv32_cfs.vhd - Custom functions subsystem +├neorv32_crc.vhd - Cyclic redundancy check unit +├neorv32_dcache.vhd - Processor-internal data cache +├neorv32_debug_dm.vhd - on-chip debugger: debug module +├neorv32_debug_dtm.vhd - on-chip debugger: debug transfer module +├neorv32_dma.vhd - Direct memory access controller +├neorv32_dmem.entity.vhd - Processor-internal data memory (entity-only!) +├neorv32_gpio.vhd - General purpose input/output port unit +├neorv32_gptmr.vhd - General purpose 32-bit timer +├neorv32_icache.vhd - Processor-internal instruction cache +├neorv32_intercon.vhd - SoC bus infrastructure +├neorv32_mtime.vhd - Machine system timer +├neorv32_neoled.vhd - NeoPixel (TM) compatible smart LED interface +├neorv32_onewire.vhd - One-Wire serial interface controller +├neorv32_pwm.vhd - Pulse-width modulation controller +├neorv32_sdi.vhd - Serial data interface controller (SPI device) +├neorv32_slink.vhd - Stream link interface +├neorv32_spi.vhd - Serial peripheral interface controller (SPI host) +├neorv32_sysinfo.vhd - System configuration information memory +├neorv32_trng.vhd - True random number generator +├neorv32_twi.vhd - Two wire serial interface controller +├neorv32_uart.vhd - Universal async. receiver/transmitter +├neorv32_wdt.vhd - Watchdog timer +├neorv32_wishbone.vhd - External (Wishbone) bus interface +├neorv32_xip.vhd - Execute in place module +├neorv32_xirq.vhd - External interrupt controller │ -├mem/neorv32_dmem.default.vhd - _Default_ data memory (architecture-only) -└mem/neorv32_imem.default.vhd - _Default_ instruction memory (architecture-only) +neorv32_top.vhd - NEORV32 Processor top entity ................................... [NOTE] @@ -287,7 +294,7 @@ https://stnolting.github.io/neorv32/ug/#_application_specific_processor_configur [cols="<2,<8"] [grid="topbot"] |======================= -| HW version: | `1.6.8.3++` +| HW version: | `1.8.6.4` | Top entity: | `rtl/core/neorv32_top.vhd` | FPGA: | Intel Cyclone IV E `EP4CE22F17C6` | Toolchain: | Quartus Prime Lite 21.1 @@ -298,35 +305,38 @@ https://stnolting.github.io/neorv32/ug/#_application_specific_processor_configur [cols="<2,<8,>1,>1,>2,>1"] [options="header",grid="rows"] |======================= -| Module | Description | LEs | FFs | MEM bits | DSPs -| Boot ROM | Bootloader ROM (4kB) | 3 | 2 | 32768 | 0 -| BUSKEEPER | Processor-internal bus monitor | 28 | 15 | 0 | 0 -| CFS | Custom functions subsystem footnote:[Resource utilization depends on custom design logic.] | - | - | - | - -| CRC | Cyclic redundancy check unit | 135 | 117 | 0 | 0 -| DM | On-chip debugger - debug module | 391 | 220 | 0 | 0 -| DMA | Direct memory access controller | 313 | 257 | 0 | 0 -| DTM | On-chip debugger - debug transfer module (JTAG) | 259 | 221 | 0 | 0 -| DMEM | Processor-internal data memory (8kB) | 18 | 2 | 65536 | 0 -| GPIO | General purpose input/output ports | 102 | 98 | 0 | 0 -| GPTMR | General Purpose Timer | 153 | 105 | 0 | 0 -| iCACHE | Instruction cache (2x4 blocks, 64 bytes per block) | 417 | 294 | 4096 | 0 -| dCACHE | Data cache (4 blocks, 64 bytes per block) | 308 | 167 | 2112 | 0 -| IMEM | Processor-internal instruction memory (16kB) | 12 | 2 | 131072 | 0 -| MTIME | Machine system timer | 345 | 166 | 0 | 0 -| NEOLED | Smart LED Interface (NeoPixel/WS28128) (FIFO_depth=1) | 227 | 184 | 0 | 0 -| ONEWIRE | 1-wire interface | 107 | 77 | 0 | 0 -| PWM | Pulse_width modulation controller (8 channels) | 128 | 117 | 0 | 0 -| SPI | Serial peripheral interface | 114 | 94 | 0 | 0 -| SLINK | Stream link interface (RX/TX FIFO depth=32) | 104 | 73 | 2048 | 0 -| SDI | Serial data interface | 72 | 66 | 0 | 0 -| SYSINFO | System configuration information memory | 13 | 11 | 0 | 0 -| TRNG | True random number generator | 89 | 79 | 0 | 0 -| TWI | Two-wire interface | 77 | 43 | 0 | 0 -| UART0, UART1 | Universal asynchronous receiver/transmitter 0/1 (FIFO_depth=1) | 195 | 143 | 0 | 0 -| WDT | Watchdog timer | 61 | 46 | 0 | 0 -| WISHBONE | External memory interface | 120 | 112 | 0 | 0 -| XIP | Execute in place module | 318 | 244 | 0 | 0 -| XIRQ | External interrupt controller (32 channels) | 245 | 200 | 0 | 0 +| Module | Description | LEs | FFs | MEM bits | DSPs +| BOOT ROM | Bootloader ROM (4kB) | 2 | 2 | 32768 | 0 +| BUSSWITCH (core) | _SoC bus infrastructure_ | 28 | 15 | 0 | 0 +| BUSSWITCH (DMA) | _SoC bus infrastructure_ | 159 | 9 | 0 | 0 +| CFS | Custom functions subsystem footnote:[Resource utilization depends on custom design logic.] | - | - | - | - +| CRC | Cyclic redundancy check unit | 130 | 117 | 0 | 0 +| dCACHE | Data cache (4 blocks, 64 bytes per block) | 300 | 167 | 2112 | 0 +| DM | On-chip debugger - debug module | 377 | 241 | 0 | 0 +| DTM | On-chip debugger - debug transfer module (JTAG) | 262 | 220 | 0 | 0 +| DMA | Direct memory access controller | 365 | 291 | 0 | 0 +| DMEM | Processor-internal data memory (8kB) | 6 | 2 | 65536 | 0 +| Gateway | _SoC bus infrastructure_ | 215 | 91 | 0 | 0 +| GPIO | General purpose input/output ports | 102 | 98 | 0 | 0 +| GPTMR | General Purpose Timer | 150 | 105 | 0 | 0 +| IO Switch | _SoC bus infrastructure_ | 217 | 0 | 0 | 0 +| iCACHE | Instruction cache (2x4 blocks, 64 bytes per block) | 458 | 296 | 4096 | 0 +| IMEM | Processor-internal instruction memory (16kB) | 7 | 2 | 131072 | 0 +| MTIME | Machine system timer | 307 | 166 | 0 | 0 +| NEOLED | Smart LED Interface (NeoPixel/WS28128) (FIFO_depth=1) | 171 | 129 | 0 | 0 +| ONEWIRE | 1-wire interface | 105 | 77 | 0 | 0 +| PWM | Pulse_width modulation controller (4 channels) | 91 | 81 | 0 | 0 +| SDI | Serial data interface | 103 | 77 | 512 | 0 +| SLINK | Stream link interface (RX/TX FIFO depth=32) | 96 | 73 | 2048 | 0 +| SPI | Serial peripheral interface | 137 | 97 | 1024 | 0 +| SYSINFO | System configuration information memory | 11 | 11 | 0 | 0 +| TRNG | True random number generator | 140 | 108 | 512 | 0 +| TWI | Two-wire interface | 93 | 64 | 0 | 0 +| UART0, UART1 | Universal asynchronous receiver/transmitter 0/1 (FIFO_depth=1) | 222 | 142 | 1024 | 0 +| WDT | Watchdog timer | 107 | 89 | 0 | 0 +| WISHBONE | External memory interface | 122 | 112 | 0 | 0 +| XIP | Execute in place module | 369 | 276 | 0 | 0 +| XIRQ | External interrupt controller (4 channels) | 35 | 29 | 0 | 0 |======================= diff --git a/docs/datasheet/soc.adoc b/docs/datasheet/soc.adoc index e516af53f..429ce2fdb 100644 --- a/docs/datasheet/soc.adoc +++ b/docs/datasheet/soc.adoc @@ -337,9 +337,10 @@ enum NEORV32_CLOCK_PRSC_enum { }; -------------------------- +.Power-Down Mode [TIP] If no peripheral modules requires a clock signal from the internal generator (all available modules disabled by clearing the -enable bit in the according module's control register), it is automatically deactivated to reduce dynamic power consumption. +enable bit in the according module's control register) the generator is automatically deactivated to reduce dynamic power consumption. @@ -456,54 +457,50 @@ A pending FIRQ has to be explicitly cleared by writing zero to the according <<_ === Address Space As a 32-bit architecture the NEORV32 can access a 4GB physical address space. By default, this address space is -divided into five main regions: - -1. **Instruction address space** for instructions (=code) and constants. A configurable section of this address space can used by the instruction memory (<<_instruction_memory_imem>>). -2. **Data address space** for application runtime data (heap, stack, etc.). A configurable section of this address space can be used by the data memory (<<_data_memory_dmem>>). -3. **Bootloader address space** for the internal bootloader memory <<_bootloader_rom_bootrom>>. -4. **On-Chip Debugger address space** for the processor's <<_on_chip_debugger_ocd>>. -5. **IO/peripheral address space**: for the processor-internal memory-mapped <<_processor_internal_modules>>. +split into six main regions. Each region provides specific _physical memory attributes_ ("PMAs") that define +the access capabilities. .NEORV32 Processor Address Space (Default Configuration) image::address_space.png[900] -.RAM Layout -[TIP] -The actual usage of the data address space by the software/executables (stack, heap, ...) is -illustrated in section <<_ram_layout>>. - - -:sectnums: -==== Physical Memory Attributes (PMAs) - -Each default region of the NEORV32 address space provides specific physical memory attributes that define the allowed access types. -The according access permission are enforced by the hardware and cannot be changed. If an access violates the PMA's permissions an -exception is raised. The access permissions can be further constrained using the CPU's <<_pmp_isa_extension>>. - -* `r` - data read access -* `w` - data write access -* `x` - instruction fetch access ("execute") - [cols="<1,^4,^2,<7"] [options="header",grid="rows"] |======================= -| # | Region Description | PMAs | Note -| 1 | Instruction address space | `r(w)x` | Write accesses to the the internal <<_instruction_memory_imem>> can be disabled. -| 2 | Data address space | `rwx` | Code can also be executed from data memory. -| 3 | Bootloader address space | `r-x` | Read-only memory. -| 4 | On-Chip Debugger address space | `---` | Not accessible at all by "normal" software - accessible only when the CPU is in <<_cpu_debug_mode>>. -| 5 | IO/peripheral address space | `rw-` | Read/write accesses only. +| # | Region | PMAs | Description +| 1 | Instruction address space | `rwx` | For instructions (=code) and constants. A configurable section of this address space can used by the internal <<_instruction_memory_imem>>. +| 2 | Data address space | `rwx` | For application runtime data (heap, stack, etc.). A configurable section of this address space can be used by the internal <<_data_memory_dmem>>). Code can also be executed from data memory. +| 3 | Memory-mapped XIP flash | `r-x` | Memory-mapped access to the <<_execute_in_place_module_xip>> SPI flash. +| 4 | Bootloader address space | `r-x` | Read-only memory for the internal <<_bootloader_rom_bootrom>> containing the default <<_bootloader>>. +| 5 | IO/peripheral address space | `rwx` | Processor-internal peripherals / IO devices. +| 6 | The "void" | `rwx` | Unmapped address space. All accesses to this region(s) are redirected to the <<_processor_external_memory_interface_wishbone>>. |======================= +The entire address space layout can be customized via the "Processor Address Space Layout" constants in the processor's +main VHDL package file (`rtl/core/neorv323_package.vhd`). -:sectnums: -==== CPU Data and Instruction Access +[source,vhdl] +---- + -- Main Address Regions --- + constant mem_ispace_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; + constant mem_dspace_base_c : std_ulogic_vector(31 downto 0) := x"80000000"; + constant mem_xip_base_c : std_ulogic_vector(31 downto 0) := x"e0000000"; + 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; +---- -The CPU can access all of the 32-bit address space from the instruction fetch interface (**I**) and also from the -data access interface (**D**). These two CPU interfaces are multiplexed by a simple bus switch -(`rtl/core/neorv32_busswitch.vhd`) into a single processor-internal bus. All processor-internal memories, peripherals -and also the external memory interface are connected to this bus. Hence, both CPU interfaces (instruction fetch & data access) -have access to the same (identical!) address space making the processor a **modified von-Neumann architecture**. +The CPU can access all of the 32-bit address space from the instruction fetch interface and also from the +data access interface. These two CPU interfaces are multiplexed by a simple bus switch into a single processor-internal +bus. Optionally, this bus is further shared by another instance of the bus switch so the DMA can controller can +also access the entire address space. + +Accesses via the resulting SoC bus are split by a gateway, that forwards accesses to the according main memory regions. +This gateway also implements a bus monitor that keeps track of active bus requests. If an accessed address responds with +an error conditions of if no response is received at all an according bus access exception is raised (see <<_bus_interface_protocol>>). +All processor-internal peripherals / IO devices are attached to an IO switch that performs the fine-granular address +decoding issuing accesses to the according module being accesses. .Processor-internal bus architecture image::neorv32_bus.png[1300] @@ -513,72 +510,9 @@ image::neorv32_bus.png[1300] The processor-internal <<_direct_memory_access_controller_dma>> has access to the same (_identical_) address space as the CPU core. +.Bus Interface [TIP] -See sections <<_architecture>> and <<_bus_interface>> for more information regarding the CPU bus accesses. - - -:sectnums: -==== Address Space Layout - -The general address space layout consists of two main configuration constants: `ispace_base_c` defining -the base address of the _instruction memory address space_ and `dspace_base_c` defining the base address of -the _data memory address space_. Both constants are defined in the NEORV32 VHDL package file -`rtl/core/neorv32_package.vhd`: - -[source,vhdl] ----- --- Architecture Configuration ---------------------------------------------------- --- ---------------------------------------------------------------------------------- -constant ispace_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; -constant dspace_base_c : std_ulogic_vector(31 downto 0) := x"80000000"; ----- - -The default configuration assumes the _instruction memory address space_ starting at address `0x00000000` -and the _data memory address space_ starting at `0x80000000`. Both values can be modified for a specific -setup and the address space may also overlap or can even be identical. - - -:sectnums: -==== Memory Configuration - -The NEORV32 Processor was designed to provide maximum flexibility for the actual memory configuration. -The processor can populate the _instruction address space_ and/or the _data address space_ with **internal memories** -for instructions (IMEM) and data (DMEM). Processor **external memories** can be used as an alternative or even in -combination with the internal ones. The figure below show some exemplary memory configurations. - -.Exemplary Memory Configurations -image::neorv32_memory_configurations.png[800] - -[NOTE] -Any access to "address holes" (addresses that do not belong to a specific module) will raise a bus exception fault -due to the missing access acknowledge. - - -:sectnums!: -===== Internal Memories - -If the processor-internal <<_instruction_memory_imem>> is implemented, it is located right at the base address of the instruction -address space (default `ispace_base_c` = _0x00000000_). Vice versa, the processor-internal <<_data_memory_dmem>> is -located right at the beginning of the data address space (default `dspace_base_c` = _0x80000000_) when implemented. - - -:sectnums!: -===== External Memories - -Any CPU access (data or instructions), which does **not** fulfill at least one of the following conditions, is forwarded -via the <<_processor_external_memory_interface_wishbone>> to external components: - -* access to the processor-internal <<_instruction_memory_imem>> and processor-internal IMEM is implemented -* access to the processor-internal <<_data_memory_dmem>> and processor-internal DMEM is implemented -* access to the processor-internal bootloader ROM and beyond - -[NOTE] -If the <<_execute_in_place_module_xip>> is implemented accesses mapped to this module are not forwarded to the -external memory interface. - -[NOTE] -If the <<_processor_external_memory_interface_wishbone>> is not implemented, any access exceeding the internal -memory address space will raise a bus access fault exception. +See sections CPU <<_architecture>> and <<_bus_interface>> for more information regarding the CPU bus accesses. :sectnums: @@ -632,10 +566,6 @@ providing an initialized external memory that contains the actual application to The NEORV32 processor is a SoC (system-on-chip) consisting of the NEORV32 CPU, peripheral/IO devices, embedded memories, an external memory interface and a bus infrastructure to interconnect all modules. -The processor-internal peripheral/IO devices are located at the end of the 32-bit address space at base -address `0xFFFFFE00`. A region of 512 bytes is reserved for these devices. Hence, all peripheral/IO devices are -accessed using a memory-mapped scheme. - .Module Address Space Mapping [IMPORTANT] The base address of each component/module has to be aligned to the total size of the module's occupied address space. @@ -643,14 +573,18 @@ The occupied address space has to be a power of two (minimum 4 bytes). Addresses .Full-Word Write Accesses Only [IMPORTANT] -All peripheral/IO devices can only be written in full-word mode (i.e. 32-bit). Byte or half-word (8/16-bit) write accesses -will raise a store access fault exception. Read accesses are not size constrained. Processor-internal memories as well as -modules connected to the external memory interface can be written with arbitrary granularity. +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 +might cause undefined behavior. -.Unimplemented Modules / "Address Holes" +.IO Module's Address Space +[IMPORTANT] +Each peripheral/IO module occupies an address space of 256 bytes (64 words). Most devices do not fully utilize this address +space and will simply _mirror_ the available interface registers across the entire 256 bytes of address space. + +.Unimplemented Modules / Address Holes [NOTE] When accessing an IO device that hast not been implemented (disabled via the according generic) -or when accessing an address that is actually unused, a load or store access fault exception is raised. +or when accessing an address that is actually unused, a load/store access fault exception is raised. .Module Interrupts [NOTE] @@ -679,8 +613,6 @@ include::soc_wishbone.adoc[] include::soc_slink.adoc[] -include::soc_buskeeper.adoc[] - include::soc_gpio.adoc[] include::soc_crc.adoc[] diff --git a/docs/datasheet/soc_buskeeper.adoc b/docs/datasheet/soc_buskeeper.adoc deleted file mode 100644 index fa9894b93..000000000 --- a/docs/datasheet/soc_buskeeper.adoc +++ /dev/null @@ -1,36 +0,0 @@ -<<< -:sectnums: -==== Internal Bus Monitor (BUSKEEPER) - -[cols="<3,<3,<4"] -[frame="topbot",grid="none"] -|======================= -| Hardware source file(s): | neorv32_buskeeper.vhd | -| Software driver file(s): | none | -| Top entity port: | none | -| Configuration generics: | none | -| Package constants: | `max_proc_int_response_time_c` | Access time window (maximum number of cycles) -| CPU interrupts: | none | -|======================= - - -**Theory of Operation** - -The Bus Keeper is a fundamental component of the processor's internal bus system that ensures correct operations -while maintaining execution safety. It operates transparently for the user by monitoring every single bus transactions -that is initiated by the CPU. If an accessed device responds with an error condition or does not respond at all within -a specific **access time window**, an according bus access fault exception is raised. The following exceptions can be -raised by the bus keeper: - -* `TRAP_CODE_I_ACCESS`: error / timeout during instruction fetch bus access -* `TRAP_CODE_S_ACCESS`: error / timeout during data store bus access -* `TRAP_CODE_L_ACCESS`: error / timeout during data load bus access - -.Access Time Window -[IMPORTANT] -The **access time window**, in which an accessed device has to respond, is defined by the `max_proc_int_response_time_c` -constant from the processor's VHDL package file (`rtl/neorv32_package.vhd`). The default value is **15 clock cycles**. - -.Register Map -[NOTE] -The bus keeper does not provide any memory-mapped interface registers at all. diff --git a/docs/datasheet/soc_cfs.adoc b/docs/datasheet/soc_cfs.adoc index 74b3d8372..2c2c6bec6 100644 --- a/docs/datasheet/soc_cfs.adoc +++ b/docs/datasheet/soc_cfs.adoc @@ -93,9 +93,9 @@ generic (default = 32-bit). The size of the output signal conduit `cfs_out_o` is [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s) | R/W | Function -| `0xfffffe00` | `REG[0]` |`31:0` | (r)/(w) | custom CFS register 0 -| `0xfffffe04` | `REG[1]` |`31:0` | (r)/(w) | custom CFS register 1 +| `0xffffeb00` | `REG[0]` |`31:0` | (r)/(w) | custom CFS register 0 +| `0xffffeb04` | `REG[1]` |`31:0` | (r)/(w) | custom CFS register 1 | ... | ... |`31:0` | (r)/(w) | ... -| `0xfffffef8` | `REG[62]` |`31:0` | (r)/(w) | custom CFS register 62 -| `0xfffffefc` | `REG[63]` |`31:0` | (r)/(w) | custom CFS register 63 +| `0xffffebf8` | `REG[62]` |`31:0` | (r)/(w) | custom CFS register 62 +| `0xffffebfc` | `REG[63]` |`31:0` | (r)/(w) | custom CFS register 63 |======================= diff --git a/docs/datasheet/soc_crc.adoc b/docs/datasheet/soc_crc.adoc index eb773dbed..1ef5449db 100644 --- a/docs/datasheet/soc_crc.adoc +++ b/docs/datasheet/soc_crc.adoc @@ -62,10 +62,10 @@ and for CRC32-mode the entire 32-bit of `POLY` and `SREG` are used. [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.2+<| `0xffffff20` .2+<| `CTRL` <|`1:0` ^| r/w <| CRC mode select (`00` CRC8, `01`: CRC16, `10`: CRC32) +.2+<| `0xffffee00` .2+<| `CTRL` <|`1:0` ^| r/w <| CRC mode select (`00` CRC8, `01`: CRC16, `10`: CRC32) <|`31:2` ^| r/- <| _reserved_, read as zero -| `0xffffff24` | `POLY` |`31:0` | r/w | CRC polynomial -.2+<| `0xffffff28` .2+<| `DATA` <|`7:0` ^| r/w <| data input (single byte) +| `0xffffee04` | `POLY` |`31:0` | r/w | CRC polynomial +.2+<| `0xffffee08` .2+<| `DATA` <|`7:0` ^| r/w <| data input (single byte) <|`31:8` ^| r/- <| _reserved_, read as zero, writes are ignored -| `0xffffff2c` | `SREG` |`32:0` | r/w | current CRC shift register value (set start value on write) +| `0xffffee0c` | `SREG` |`32:0` | r/w | current CRC shift register value (set start value on write) |======================= diff --git a/docs/datasheet/soc_dcache.adoc b/docs/datasheet/soc_dcache.adoc index 9be026bcb..588881376 100644 --- a/docs/datasheet/soc_dcache.adoc +++ b/docs/datasheet/soc_dcache.adoc @@ -23,10 +23,13 @@ The cache is implemented if the `DCACHE_EN` generic is `true`. The size of the c equal to 4 bytes) and `DCACHE_NUM_BLOCKS` (the total amount of cache blocks; has to be a power of two and greater than or equal to 1) generics. The data cache provides only a single set, hence it is direct-mapped. + +**Cached/Unached Accesses** + The data cache provides direct accesses (= uncached) to memory in order to access memory-mapped IO (like the processor-internal IO/peripheral modules). All accesses that target the address range from `0xF0000000` to `0xFFFFFFFF` -will not be cached at all. This also allows to attach custom IO modules via the processor's external memory interface -when they are mapped to upper-most 256 MB address page (see section <<_address_space>>). +will not be cached at all (see section <<_address_space>>). + .Caching Internal Memories [NOTE] diff --git a/docs/datasheet/soc_dma.adoc b/docs/datasheet/soc_dma.adoc index 0bf56d628..0975ada8b 100644 --- a/docs/datasheet/soc_dma.adoc +++ b/docs/datasheet/soc_dma.adoc @@ -122,7 +122,7 @@ explicitly cleared again by writing zero to the according <<_mip>> CSR bit. [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.8+<| `0xffffff10` .8+<| `CTRL` <|`0` `DMA_CTRL_EN` ^| r/w <| DMA module enable +.8+<| `0xffffed00` .8+<| `CTRL` <|`0` `DMA_CTRL_EN` ^| r/w <| DMA module enable <|`1` `DMA_CTRL_AUTO` ^| r/w <| Enable automatic mode (FIRQ-triggered) <|`7:2` _reserved_ ^| r/- <| reserved, read as zero <|`8` `DMA_CTRL_ERROR_RD` ^| r/- <| Error during read access, clears when starting a new transfer @@ -130,9 +130,9 @@ explicitly cleared again by writing zero to the according <<_mip>> CSR bit. <|`10` `DMA_CTRL_BUSY` ^| r/- <| DMA transfer in progress <|`15:11` _reserved_ ^| r/- <| reserved, read as zero <|`31:16` `DMA_CTRL_FIRQ_MASK_MSB : DMA_CTRL_FIRQ_MASK_LSB` ^| r/w <| FIRQ trigger mask (same bits as in <<_mip>>) -| `0xffffff14` | `SRC_BASE` |`31:0` | r/w | Source base address (shows the last-accessed source address when read) -| `0xffffff18` | `DST_BASE` |`31:0` | r/w | Destination base address (shows the last-accessed destination address when read) -.6+<| `0xffffff1c` .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) +| `0xffffed04` | `SRC_BASE` |`31:0` | r/w | Source base address (shows the last-accessed source address when read) +| `0xffffed08` | `DST_BASE` |`31:0` | r/w | Destination base address (shows the last-accessed destination address when read) +.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) <|`26:24` _reserved_ ^| r/- <| reserved, read as zero <|`28:27` `DMA_TTYPE_QSEL_MSB : DMA_TTYPE_QSEL_LSB` ^| r/w <| Source data quantity select (`00` = byte, `01` = half-word, `10` = word) <|`29` `DMA_TTYPE_SRC_INC` ^| r/w <| Constant (`0`) or incrementing (`1`) source address diff --git a/docs/datasheet/soc_gpio.adoc b/docs/datasheet/soc_gpio.adoc index 6886578b9..2e2fceb84 100644 --- a/docs/datasheet/soc_gpio.adoc +++ b/docs/datasheet/soc_gpio.adoc @@ -37,8 +37,8 @@ be performed within a single clock cycle. [options="header",grid="rows"] |======================= | Address | Name [C] | Bit(s) | R/W | Function -| `0xffffffc0` | `INPUT_LO` | 31:0 | r/- | parallel input port pins 31:0 -| `0xffffffc4` | `INPUT_HI` | 31:0 | r/- | parallel input port pins 63:32 -| `0xffffffc8` | `OUTPUT_LO` | 31:0 | r/w | parallel output port pins 31:0 -| `0xffffffcc` | `OUTPUT_HI` | 31:0 | r/w | parallel output port pins 63:32 +| `0xfffffc00` | `INPUT_LO` | 31:0 | r/- | parallel input port pins 31:0 +| `0xfffffc04` | `INPUT_HI` | 31:0 | r/- | parallel input port pins 63:32 +| `0xfffffc08` | `OUTPUT_LO` | 31:0 | r/w | parallel output port pins 31:0 +| `0xfffffc0c` | `OUTPUT_HI` | 31:0 | r/w | parallel output port pins 63:32 |======================= diff --git a/docs/datasheet/soc_gptmr.adoc b/docs/datasheet/soc_gptmr.adoc index fcfb34e6b..cae926563 100644 --- a/docs/datasheet/soc_gptmr.adoc +++ b/docs/datasheet/soc_gptmr.adoc @@ -57,10 +57,10 @@ remains pending inside the CPU until it explicitly cleared by writing zero to th [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.4+<| `0xffffff60` .4+<| `CTRL` <|`0` `GPTMR_CTRL_EN` ^| r/w <| Timer enable flag +.4+<| `0xfffff100` .4+<| `CTRL` <|`0` `GPTMR_CTRL_EN` ^| r/w <| Timer enable flag <|`3:1` `GPTMR_CTRL_PRSC2 : GPTMR_CTRL_PRSC0` ^| r/w <| 3-bit clock prescaler select <|`4` `GPTMR_CTRL_MODE` ^| r/w <| Counter mode: `0`=single-shot, `1`=continuous <|`31:5` - ^| r/- <| _reserved_, read as zero -| `0xffffff64` | `THRES` |`31:0` | r/w | Threshold value register -| `0xffffff68` | `COUNT` |`31:0` | r/w | Counter register +| `0xfffff104` | `THRES` |`31:0` | r/w | Threshold value register +| `0xfffff108` | `COUNT` |`31:0` | r/w | Counter register |======================= diff --git a/docs/datasheet/soc_icache.adoc b/docs/datasheet/soc_icache.adoc index 8ec9dca74..31f25de80 100644 --- a/docs/datasheet/soc_icache.adoc +++ b/docs/datasheet/soc_icache.adoc @@ -5,9 +5,9 @@ [cols="<3,<3,<4"] [frame="topbot",grid="none"] |======================= -| Hardware source file(s): | neorv32_icache.vhd | -| Software driver file(s): | none | _implicitly used_ -| Top entity port: | none | +| Hardware source file(s): | neorv32_icache.vhd | +| Software driver file(s): | none | _implicitly used_ +| Top entity port: | none | | Configuration generics: | `ICACHE_EN` | implement processor-internal instruction cache when `true` | | `ICACHE_NUM_BLOCKS` | number of cache blocks (pages/lines) | | `ICACHE_BLOCK_SIZE` | size of a cache block in bytes @@ -26,6 +26,14 @@ equal to 1) and the actual cache associativity `ICACHE_ASSOCIATIVITY` (number of set-associative) generics. If the cache associativity is greater than one the LRU replacement policy (least recently used) is used. + +**Cached/Unached Accesses** + +The data cache provides direct accesses (= uncached) to memory in order to access memory-mapped IO (like the +processor-internal IO/peripheral modules). All accesses that target the address range from `0xF0000000` to `0xFFFFFFFF` +will not be cached at all (see section <<_address_space>>). + + .Caching Internal Memories [NOTE] The instruction cache is intended to accelerate instruction fetches from **processor-external** memories diff --git a/docs/datasheet/soc_mtime.adoc b/docs/datasheet/soc_mtime.adoc index 4efa39002..70a437890 100644 --- a/docs/datasheet/soc_mtime.adoc +++ b/docs/datasheet/soc_mtime.adoc @@ -39,8 +39,8 @@ the interrupt request is explicitly acknowledged (e.g. writing to a memory-mappe [options="header",grid="all"] |======================= | Address | Name [C] | Bits | R/W | Function -| `0xffffff90` | `TIME_LO` | 31:0 | r/w | machine system time, low word -| `0xffffff94` | `TIME_HI` | 31:0 | r/w | machine system time, high word -| `0xffffff98` | `TIMECMP_LO` | 31:0 | r/w | time compare, low word -| `0xffffff9c` | `TIMECMP_HI` | 31:0 | r/w | time compare, high word +| `0xfffff400` | `TIME_LO` | 31:0 | r/w | machine system time, low word +| `0xfffff404` | `TIME_HI` | 31:0 | r/w | machine system time, high word +| `0xfffff408` | `TIMECMP_LO` | 31:0 | r/w | time compare, low word +| `0xfffff40c` | `TIMECMP_HI` | 31:0 | r/w | time compare, high word |======================= diff --git a/docs/datasheet/soc_neoled.adoc b/docs/datasheet/soc_neoled.adoc index bdb79798d..7e35cc03f 100644 --- a/docs/datasheet/soc_neoled.adoc +++ b/docs/datasheet/soc_neoled.adoc @@ -186,7 +186,7 @@ writing zero to according <<_mip>> CSR bit. [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.13+<| `0xffffffd8` .13+<| `CTRL` <|`0` `NEOLED_CTRL_EN` ^| r/w <| NEOLED enable +.13+<| `0xfffffd00` .13+<| `CTRL` <|`0` `NEOLED_CTRL_EN` ^| r/w <| NEOLED enable <|`1` `NEOLED_CTRL_MODE` ^| r/w <| data transfer size; `0`=24-bit; `1`=32-bit <|`2` `NEOLED_CTRL_STROBE` ^| r/w <| `0`=send normal color data; `1`=send RESET command on data write access <|`5:3` `NEOLED_CTRL_PRSC2 : NEOLED_CTRL_PRSC0` ^| r/w <| 3-bit clock prescaler, bit 0 @@ -199,5 +199,5 @@ writing zero to according <<_mip>> CSR bit. <|`29` `NEOLED_CTRL_TX_HALF` ^| r/- <| TX FIFO is _at least_ half full <|`30` `NEOLED_CTRL_TX_FULL` ^| r/- <| TX FIFO is full <|`31` `NEOLED_CTRL_TX_BUSY` ^| r/- <| TX serial engine is busy when set -| `0xffffffdc` | `DATA` <|`31:0` / `23:0` ^| -/w <| TX data (32- or 24-bit, depending on _NEOLED_CTRL_MODE_ bit) +| `0xfffffd04` | `DATA` <|`31:0` / `23:0` ^| -/w <| TX data (32- or 24-bit, depending on _NEOLED_CTRL_MODE_ bit) |======================= diff --git a/docs/datasheet/soc_onewire.adoc b/docs/datasheet/soc_onewire.adoc index ab9364a8b..612a6cad9 100644 --- a/docs/datasheet/soc_onewire.adoc +++ b/docs/datasheet/soc_onewire.adoc @@ -176,7 +176,7 @@ according <<_mip>> CSR FIRQ bit. [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.10+<| `0xffffff70` .10+<| `CTRL` <|`0` `ONEWIRE_CTRL_EN` ^| r/w <| ONEWIRE enable, reset if cleared +.10+<| `0xfffff200` .10+<| `CTRL` <|`0` `ONEWIRE_CTRL_EN` ^| r/w <| ONEWIRE enable, reset if cleared <|`2:1` `ONEWIRE_CTRL_PRSC1 : ONEWIRE_CTRL_PRSC0` ^| r/w <| 2-bit clock prescaler select <|`10:3` `ONEWIRE_CTRL_CLKDIV7 : ONEWIRE_CTRL_CLKDIV0` ^| r/w <| 8-bit clock divider value <|`11` `ONEWIRE_CTRL_TRIG_RST` ^| -/w <| trigger reset pulse, auto-clears @@ -186,5 +186,5 @@ according <<_mip>> CSR FIRQ bit. <|`29` `ONEWIRE_CTRL_SENSE` ^| r/- <| current state of the bus line <|`30` `ONEWIRE_CTRL_PRESENCE` ^| r/- <| device presence detected after reset pulse <|`31` `ONEWIRE_CTRL_BUSY` ^| r/- <| operation in progress when set -| `0xffffff74` | `DATA` |`7:0` `ONEWIRE_DATA_MSB : ONEWIRE_DATA_LSB` | r/w | receive/transmit data (8-bit) +| `0xfffff204` | `DATA` |`7:0` `ONEWIRE_DATA_MSB : ONEWIRE_DATA_LSB` | r/w | receive/transmit data (8-bit) |======================= \ No newline at end of file diff --git a/docs/datasheet/soc_pwm.adoc b/docs/datasheet/soc_pwm.adoc index 93bf22eb4..97e1a3100 100644 --- a/docs/datasheet/soc_pwm.adoc +++ b/docs/datasheet/soc_pwm.adoc @@ -67,18 +67,18 @@ _**f~PWM~**_ = _f~main~[Hz]_ / (2^8^ * `clock_prescaler`) [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.3+<| `0xffffff50` .3+<| `CTRL` <|`0` `PWM_CTRL_EN` ^| r/w <| PWM enable +.3+<| `0xfffff000` .3+<| `CTRL` <|`0` `PWM_CTRL_EN` ^| r/w <| PWM enable <|`3:1` `PWM_CTRL_PRSC2 : PWM_CTRL_PRSC0` ^| r/w <| 3-bit clock prescaler select <|`31:4` - ^| r/- <| _reserved_, read as zero -.4+<| `0xffffff54` .4+<| `DC[0]` <|`7:0` ^| r/w <| 8-bit duty cycle for channel 0 +.4+<| `0xfffff004` .4+<| `DC[0]` <|`7:0` ^| r/w <| 8-bit duty cycle for channel 0 <|`15:8` ^| r/w <| 8-bit duty cycle for channel 1 <|`23:16` ^| r/w <| 8-bit duty cycle for channel 2 <|`31:24` ^| r/w <| 8-bit duty cycle for channel 3 -.4+<| `0xffffff58` .4+<| `DC[1]` <|`7:0` ^| r/w <| 8-bit duty cycle for channel 4 +.4+<| `0xfffff008` .4+<| `DC[1]` <|`7:0` ^| r/w <| 8-bit duty cycle for channel 4 <|`15:8` ^| r/w <| 8-bit duty cycle for channel 5 <|`23:16` ^| r/w <| 8-bit duty cycle for channel 6 <|`31:24` ^| r/w <| 8-bit duty cycle for channel 7 -.4+<| `0xffffff5c` .4+<| `DC[2]` <|`7:0` ^| r/w <| 8-bit duty cycle for channel 8 +.4+<| `0xfffff00c` .4+<| `DC[2]` <|`7:0` ^| r/w <| 8-bit duty cycle for channel 8 <|`15:8` ^| r/w <| 8-bit duty cycle for channel 9 <|`23:16` ^| r/w <| 8-bit duty cycle for channel 10 <|`31:24` ^| r/w <| 8-bit duty cycle for channel 11 diff --git a/docs/datasheet/soc_sdi.adoc b/docs/datasheet/soc_sdi.adoc index 98f93796d..34426486f 100644 --- a/docs/datasheet/soc_sdi.adoc +++ b/docs/datasheet/soc_sdi.adoc @@ -82,7 +82,7 @@ Furthermore, an active SDI interrupt has to be explicitly cleared again by writi [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.16+<| `0xfffffff0` .16+<| `CTRL` <|`0` `SDI_CTRL_EN` ^| r/w <| SDI module enable +.16+<| `0xfffff700` .16+<| `CTRL` <|`0` `SDI_CTRL_EN` ^| r/w <| SDI module enable <|`1` `SDI_CTRL_CLR_RX` ^| -/w <| clear RX FIFO when set, bit auto-clears <|`3:2` _reserved_ ^| r/- <| reserved, read as zero <|`7:4` `SDI_CTRL_FIFO_MSB : SDI_CTRL_FIFO_LSB` ^| r/- <| FIFO depth; log2(_IO_SDI_FIFO_) @@ -98,5 +98,5 @@ Furthermore, an active SDI interrupt has to be explicitly cleared again by writi <|`26` `SDI_CTRL_TX_EMPTY` ^| r/- <| TX FIFO empty <|`27` `SDI_CTRL_TX_FULL` ^| r/- <| TX FIFO full <|`31:28` _reserved_ ^| r/- <| reserved, read as zero -| `0xfffffff4` | `DATA` |`7:0` | r/w | receive/transmit data (FIFO) +| `0xfffff704` | `DATA` |`7:0` | r/w | receive/transmit data (FIFO) |======================= diff --git a/docs/datasheet/soc_slink.adoc b/docs/datasheet/soc_slink.adoc index ee3c999aa..b750a8dc5 100644 --- a/docs/datasheet/soc_slink.adoc +++ b/docs/datasheet/soc_slink.adoc @@ -76,7 +76,7 @@ it has to be explicitly cleared again by writing zero to the according <<_mip>> [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s) | R/W | Function -.20+<| `0xffffff08` .20+<| `NEORV32_SLINK.CTRL` <| `0` `SLINK_CTRL_EN` ^| r/w | SLINK global enable +.20+<| `0xffffec00` .20+<| `NEORV32_SLINK.CTRL` <| `0` `SLINK_CTRL_EN` ^| r/w | SLINK global enable <| `1` `SLINK_CTRL_RX_CLR` ^| -/w | Clear RX FIFO (bit auto-clears) <| `2` `SLINK_CTRL_TX_CLR` ^| -/w | Clear TX FIFO (bit auto-clears) <| `7:3` _reserved_ ^| r/- | _reserved_, read as zero @@ -96,5 +96,5 @@ it has to be explicitly cleared again by writing zero to the according <<_mip>> <| `23:22` _reserved_ ^| r/- | _reserved_, read as zero <| `27:24` `SLINK_CTRL_RX_FIFO_MSB : SLINK_CTRL_RX_FIFO_LSB` ^| r/- | log2(RX FIFO size) <| `31:28` `SLINK_CTRL_TX_FIFO_MSB : SLINK_CTRL_TX_FIFO_LSB` ^| r/- | log2(TX FIFO size) -| `0xffffff0c` | `NEORV32_SLINK.DATA` | `31:0` | r/w | RX/TX data +| `0xffffec04` | `NEORV32_SLINK.DATA` | `31:0` | r/w | RX/TX data |======================= diff --git a/docs/datasheet/soc_spi.adoc b/docs/datasheet/soc_spi.adoc index 8cea9a745..0fd078af3 100644 --- a/docs/datasheet/soc_spi.adoc +++ b/docs/datasheet/soc_spi.adoc @@ -107,7 +107,7 @@ Furthermore, an active SPI interrupt has to be explicitly cleared again by writi [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.18+<| `0xffffffa8` .18+<| `CTRL` <|`0` `SPI_CTRL_EN` ^| r/w <| SPI module enable +.18+<| `0xfffff800` .18+<| `CTRL` <|`0` `SPI_CTRL_EN` ^| r/w <| SPI module enable <|`1` `SPI_CTRL_CPHA` ^| r/w <| clock phase <|`2` `SPI_CTRL_CPOL` ^| r/w <| clock polarity <|`5:3` `SPI_CTRL_CS_SEL2 : SPI_CTRL_CS_SEL0` ^| r/w <| Direct chip-select 0..7 @@ -125,5 +125,5 @@ Furthermore, an active SPI interrupt has to be explicitly cleared again by writi <|`26:23` `SPI_CTRL_FIFO_MSB : SPI_CTRL_FIFO_LSB` ^| r/- <| FIFO depth; log2(_IO_SPI_FIFO_) <|`30:27` `reserved_ ^| r/- <| reserved, read as zero <|`31` `SPI_CTRL_BUSY` ^| r/- <| SPI module busy when set (serial engine operation in progress and TX FIFO not empty yet) -| `0xffffffac` | `DATA` |`7:0` | r/w | receive/transmit data (FIFO) +| `0xfffff804` | `DATA` |`7:0` | r/w | receive/transmit data (FIFO) |======================= diff --git a/docs/datasheet/soc_sysinfo.adoc b/docs/datasheet/soc_sysinfo.adoc index 20a73bbb3..b438606d9 100644 --- a/docs/datasheet/soc_sysinfo.adoc +++ b/docs/datasheet/soc_sysinfo.adoc @@ -33,14 +33,14 @@ Any write access to the SYSINFO module will raise a store bus error exception. [options="header",grid="all"] |======================= | Address | Name [C] | Function -| `0xffffffe0` | `CLK` | clock speed in Hz (via top's `CLOCK_FREQUENCY` generic) -| `0xffffffe4` | `CUSTOM_ID | custom user-defined ID (via top's `CUSTOM_ID` generic) -| `0xffffffe8` | `SOC` | specific SoC configuration (see `sysinfo_soc_configuration>>) -| `0xffffffec` | `CACHE` | cache configuration information (see <<_sysinfo_cache_configuration>>) -| `0xfffffff0` | `ISPACE_BASE` | instruction address space base (via package's `ispace_base_c` constant) -| `0xfffffff4` | `IMEM_SIZE` | internal IMEM size in bytes (via top's `MEM_INT_IMEM_SIZE` generic) -| `0xfffffff8` | `DSPACE_BASE` | data address space base (via package's `sdspace_base_c` constant) -| `0xfffffffc` | `DMEM_SIZE` | internal DMEM size in bytes (via top's `MEM_INT_DMEM_SIZE` generic) +| `0xfffffe00` | `CLK` | clock speed in Hz (via top's `CLOCK_FREQUENCY` generic) +| `0xfffffe04` | `CUSTOM_ID | custom user-defined ID (via top's `CUSTOM_ID` generic) +| `0xfffffe08` | `SOC` | specific SoC configuration (see `sysinfo_soc_configuration>>) +| `0xfffffe0c` | `CACHE` | cache configuration information (see <<_sysinfo_cache_configuration>>) +| `0xfffffe10` | `ISPACE_BASE` | instruction address space base (via package's `ispace_base_c` constant) +| `0xfffffe14` | `IMEM_SIZE` | internal IMEM size in bytes (via top's `MEM_INT_IMEM_SIZE` generic) +| `0xfffffe18` | `DSPACE_BASE` | data address space base (via package's `sdspace_base_c` constant) +| `0xfffffe1c` | `DMEM_SIZE` | internal DMEM size in bytes (via top's `MEM_INT_DMEM_SIZE` generic) |======================= diff --git a/docs/datasheet/soc_trng.adoc b/docs/datasheet/soc_trng.adoc index 76692e384..8f9fbc93a 100644 --- a/docs/datasheet/soc_trng.adoc +++ b/docs/datasheet/soc_trng.adoc @@ -71,7 +71,7 @@ an active TRNG interrupt has to be explicitly cleared again by writing zero to t [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.11+<| `0xffffffb8` .11+<| `CTRL` <|`7:0` `TRNG_CTRL_DATA_MSB : TRNG_CTRL_DATA_MSB` ^| r/- <| 8-bit random data +.11+<| `0xfffffa00` .11+<| `CTRL` <|`7:0` `TRNG_CTRL_DATA_MSB : TRNG_CTRL_DATA_MSB` ^| r/- <| 8-bit random data <|`15:8` - ^| r/- <| reserved, read as zero <|`19:16` `TRNG_CTRL_FIFO_MSB : TRNG_CTRL_FIFO_MSB` ^| r/- <| FIFO depth, log2(`IO_TRNG_FIFO`) <|`25:20` - ^| r/- <| reserved, read as zero diff --git a/docs/datasheet/soc_twi.adoc b/docs/datasheet/soc_twi.adoc index f28c887bd..1ed74a3f5 100644 --- a/docs/datasheet/soc_twi.adoc +++ b/docs/datasheet/soc_twi.adoc @@ -125,7 +125,7 @@ explicitly cleared again by writing zero to the according <<_mip>> CSR bit. [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.10+<| `0xffffffb0` .10+<| `CTRL` <|`0` `TWI_CTRL_EN` ^| r/w <| TWI enable, reset if cleared +.10+<| `0xfffff900` .10+<| `CTRL` <|`0` `TWI_CTRL_EN` ^| r/w <| TWI enable, reset if cleared <|`1` `TWI_CTRL_START` ^| -/w <| generate START condition, auto-clears <|`2` `TWI_CTRL_STOP` ^| -/w <| generate STOP condition, auto-clears <|`3` `TWI_CTRL_MACK` ^| r/w <| generate controller-ACK for each transmission ("MACK") @@ -136,5 +136,5 @@ explicitly cleared again by writing zero to the according <<_mip>> CSR bit. <|`29` `TWI_CTRL_CLAIMED` ^| r/- <| set if the TWI bus is claimed by any controller <|`30` `TWI_CTRL_ACK` ^| r/- <| ACK received when set, NACK received when cleared <|`31` `TWI_CTRL_BUSY` ^| r/- <| transfer/START/STOP in progress when set -| `0xffffffb4` | `DATA` |`7:0` | r/w | receive/transmit data +| `0xfffff904` | `DATA` |`7:0` | r/w | receive/transmit data |======================= diff --git a/docs/datasheet/soc_uart.adoc b/docs/datasheet/soc_uart.adoc index b5fd727e6..8763d97e6 100644 --- a/docs/datasheet/soc_uart.adoc +++ b/docs/datasheet/soc_uart.adoc @@ -122,7 +122,7 @@ Both file are created in the simulation's home folder. [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.19+<| `0xffffffa0` .19+<| `CTRL` <|`0` `UART_CTRL_EN` ^| r/w <| UART enable +.19+<| `0xfffff500` .19+<| `CTRL` <|`0` `UART_CTRL_EN` ^| r/w <| UART enable <|`1` `UART_CTRL_SIM_MODE` ^| r/w <| enable **simulation mode** <|`2` `UART_CTRL_HWFC_EN` ^| r/w <| enable RTS/CTS hardware flow-control <|`5:3` `UART_CTRL_PRSC2 : UART_CTRL_PRSC0` ^| r/w <| Baud rate clock prescaler select @@ -141,7 +141,7 @@ Both file are created in the simulation's home folder. <|`29:27` - ^| r/- <| _reserved_ read as zero <|`30` `UART_CTRL_RX_OVER` ^| r/- <| RX FIFO overflow <|`31` `UART_CTRL_TX_BUSY` ^| r/- <| TX busy or TX FIFO not empty -.5+<| `0xffffffa4` .3+<| `DATA` <|`7:0` `UART_DATA_RTX_MSB : UART_DATA_RTX_LSB` ^| r/w <| receive/transmit data +.5+<| `0xfffff504` .3+<| `DATA` <|`7:0` `UART_DATA_RTX_MSB : UART_DATA_RTX_LSB` ^| r/w <| receive/transmit data <|`11:8` `UART_DATA_RX_FIFO_SIZE_MSB : UART_DATA_RX_FIFO_SIZE_LSB` ^| r/- <| log2(RX FIFO size) <|`15:12` `UART_DATA_TX_FIFO_SIZE_MSB : UART_DATA_TX_FIFO_SIZE_LSB` ^| r/- <| log2(RX FIFO size) <|`31:16` ^| r/- <| _reserved_, read as zero @@ -196,6 +196,6 @@ data words. [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -| `0xffffffd0` | `CTRL` | ... | ... | Same as UART0 -| `0xffffffd4` | `DATA` | ... | ... | Same as UART0 +| `0xfffff600` | `CTRL` | ... | ... | Same as UART0 +| `0xfffff604` | `DATA` | ... | ... | Same as UART0 |======================= diff --git a/docs/datasheet/soc_wdt.adoc b/docs/datasheet/soc_wdt.adoc index 8c462f3ad..d436945c5 100644 --- a/docs/datasheet/soc_wdt.adoc +++ b/docs/datasheet/soc_wdt.adoc @@ -84,7 +84,7 @@ the last system reset was caused by the watchdog itself. [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Reset value | Writable if locked | Function -.8+<| `0xffffffbc` .8+<| `CTRL` <|`0` `WDT_CTRL_EN` ^| r/w ^| `0` ^| no <| watchdog enable +.8+<| `0xfffffb00` .8+<| `CTRL` <|`0` `WDT_CTRL_EN` ^| r/w ^| `0` ^| no <| watchdog enable <|`1 `WDT_CTRL_LOCK` ^| r/w ^| `0` ^| no <| lock configuration when set, clears only on system reset, can only be set if enable bit is set already <|`2` `WDT_CTRL_DBEN` ^| r/w ^| `0` ^| no <| set to allow WDT to continue operation even when CPU is in debug mode <|`3` `WDT_CTRL_SEN` ^| r/w ^| `0` ^| no <| set to allow WDT to continue operation even when CPU is in sleep mode diff --git a/docs/datasheet/soc_wishbone.adoc b/docs/datasheet/soc_wishbone.adoc index 2a4b496ac..d4602e5b1 100644 --- a/docs/datasheet/soc_wishbone.adoc +++ b/docs/datasheet/soc_wishbone.adoc @@ -31,25 +31,11 @@ The external memory interface provides a Wishbone b4-compatible on-chip bus interface. The bus interface is implemented if the `MEM_EXT_EN` generic is `true`. This interface can be used to attach external memories, -custom hardware accelerators, additional IO devices or all other kinds of IP blocks to the processor. +custom hardware accelerators, additional IO devices or all other kinds of IP blocks. The external interface is not mapped to a specific address space. Instead, all CPU memory accesses that -do not target a processor-internal module are delegated to the external memory interface. In summary, a CPU load/store -access is delegated via the external bus interface if... - -* the access does not target the internal instruction memory IMEM (if implemented at all) -* **and** the access does not target the internal data memory DMEM (if implemented at all) -* **and** the access does not target the internal bootloader ROM or any of the internal modules - regardless -if one or more of these components are actually implemented or not. - -.Address Space Layout -[TIP] -See section <<_address_space>> for more information. - -.Execute-in-Place Module -[NOTE] -If the Execute In Place module (XIP) is implemented, accesses targeting the XIP memory-mapped-region will not be forwarded to the -external memory interface. See section <<_execute_in_place_module_xip>> for more information. +do not target a specific processor-internal address region (accessing the "void"; see section <<_address_space>>) +are redirected to the external memory interface. **Wishbone Bus Protocol** @@ -81,7 +67,7 @@ project. **Bus Access** -The NEORV32 Wishbone gateway does not support burst transfer yet, so there is always just a single transfer "in fly". +The NEORV32 Wishbone gateway does not support burst transfers yet, so there is always just a single transfer "in fly". Hence, the Wishbone `STALL` signal is not implemented. An accessed Wishbone device does not have to respond immediately to a bus request by sending an ACK. Instead, there is a _time window_ where the device has to acknowledge the transfer. This time window s configured by the `MEM_EXT_TIMEOUT` generic that defines the maximum time (in clock cycles) a bus access can be pending diff --git a/docs/datasheet/soc_xip.adoc b/docs/datasheet/soc_xip.adoc index e81db42a9..6dc270c0d 100644 --- a/docs/datasheet/soc_xip.adoc +++ b/docs/datasheet/soc_xip.adoc @@ -19,12 +19,8 @@ **Overview** -The execute in-place (XIP) module allows to execute code (and read constant data) directly from a SPI flash memory. -Hence, it uses the standard serial peripheral interface (SPI) as transfer protocol under the hood. - -The XIP flash is not mapped to a specific region of the processor's address space. Instead, it -provides a programmable mapping scheme to allow a flexible user-defined mapping of the flash to _any section_ -of the address space. +The execute in-place (XIP) module allows to execute code (and read constant data) directly from an external SPI flash memory. +The standard serial peripheral interface (SPI) is used as transfer protocol. From the CPU side, the modules provides two different interfaces: one for transparently accessing the XIP flash and another one for accessing the module's control and status registers. The first interface provides a _transparent_ @@ -33,6 +29,11 @@ Note that this interface is read-only. Any write access will raise a bus error e The second interface is mapped to the processor's IO space and allows data accesses to the XIP module's configuration registers. +.XIP Address Mapping +[NOTE] +When XIP mode is enabled the flash is mapped to fixed address space region starting at address +`0xE0000000` (see section <<_address_space>>). + .XIP Example Program [TIP] An example program is provided in `sw/example/demo_xip` that illustrate how to program and configure @@ -99,20 +100,6 @@ When the XIP mode is not enabled, the XIP module can also be used as additional with a transfer size of up to 64 bits per transmission. -**Address Mapping** - -The address mapping of the XIP flash is not fixed by design. It can be mapped to _any section_ within the processor's -address space. A _section_ refers to one out of 16 naturally aligned 256MB wide memory segments. This segment -is defined by the four most significant bits of the address (`31:28`) and the XIP's segment is programmed by the -four `XIP_CTRL_XIP_PAGE` bits in the unit's control register. All accesses within this page will be mapped to the XIP flash. - -.Page Mapping -[IMPORTANT] -Care must be taken when programming the page mapping to prevent access collisions with other modules (like internal memories -or modules attached to the external memory interface). Do not use page `0xF` (base address `0xF000_0000`) as this will -prevent access to the internal peripherals - including the XIP control registers themselves. - - **Using the XIP Mode** The XIP module is globally enabled by setting the `XIP_CTRL_EN` bit in the device's `CTRL` control register. @@ -148,16 +135,16 @@ The XIP mode requires the 4-byte data words in the flash to be ordered in **litt After the SPI properties (including the amount of address bytes **and** the total amount of SPI transfer bytes) and XIP address mapping are configured, the actual XIP mode can be enabled by setting the control register's `XIP_CTRL_XIP_EN` bit. This will enable the "transparent SPI access port" of the module and thus, -the _transparent_ conversion of access requests into proper SPI flash transmissions. Make sure `XIP_CTRL_SPI_CSEN` -is also set so the module can actually select/enable the attached SPI flash. +the _transparent_ conversion of access requests into proper SPI flash transmissions. Hence, any access to the processor's +memory-mapped XIP region (`0xE0000000` to `0xEFFFFFFF`) will be converted into SPI flash accesses. +Make sure `XIP_CTRL_SPI_CSEN` is also set so the module can actually select/enable the attached SPI flash. No more direct SPI accesses via `DATA_HI:DATA_LO` are possible when the XIP mode is enabled. However, the XIP mode can be disabled at any time. [NOTE] -If the XIP module is disabled (_XIP_CTRL_EN_ = `0`) any accesses to the programmed XIP memory segment are ignored -by the module and might be forwarded to the processor's external memory interface (if implemented) or will cause a bus -exception. If the XIP module is enabled (_XIP_CTRL_EN_ = `1`) but XIP mode is not enabled yet (_XIP_CTRL_XIP_EN_ = '0') -any access to the programmed XIP memory segment will raise a bus exception. +If the XIP module is disabled (_XIP_CTRL_EN_ = `0`) any accesses to the memory-mapped XIP flash address region +will raise a bus access exception. If the XIP module is enabled (_XIP_CTRL_EN_ = `1`) but XIP mode is not enabled +yet (_XIP_CTRL_XIP_EN_ = '0') any access to the programmed XIP memory segment will also raise a bus access exception. [TIP] It is highly recommended to enable the <<_processor_internal_instruction_cache_icache>> to cover some @@ -183,7 +170,7 @@ By using the XIP burst mode flash read accesses can be accelerated by up to 50%. [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.15+<| `0xffffff40` .15+<| `CTRL` <|`0` `XIP_CTRL_EN` ^| r/w <| XIP module enable +.14+<| `0xffffff40` .14+<| `CTRL` <|`0` `XIP_CTRL_EN` ^| r/w <| XIP module enable <|`3:1` `XIP_CTRL_PRSC2 : XIP_CTRL_PRSC0` ^| r/w <| 3-bit SPI clock prescaler select <|`4` `XIP_CTRL_CPOL` ^| r/w <| SPI clock polarity <|`5` `XIP_CTRL_CPHA` ^| r/w <| SPI clock phase @@ -191,10 +178,9 @@ By using the XIP burst mode flash read accesses can be accelerated by up to 50%. <|`10` `XIP_CTRL_XIP_EN` ^| r/w <| XIP mode enable <|`12:11` `XIP_CTRL_XIP_ABYTES_MSB : XIP_CTRL_XIP_ABYTES_LSB` ^| r/w <| Number of address bytes for XIP flash (minus 1) <|`20:13` `XIP_CTRL_RD_CMD_MSB : XIP_CTRL_RD_CMD_LSB` ^| r/w <| Flash read command - <|`24:21` `XIP_CTRL_XIP_PAGE_MSB : XIP_CTRL_XIP_PAGE_LSB` ^| r/w <| XIP memory page - <|`25` `XIP_CTRL_SPI_CSEN` ^| r/w <| Allow SPI chip-select to be actually asserted when set - <|`26` `XIP_CTRL_HIGHSPEED` ^| r/w <| enable SPI high-speed mode (ignoring _XIP_CTRL_PRSC_) - <|`27` `XIP_CTRL_BURST_EN` ^| r/w <| Enable XIP burst mode + <|`21` `XIP_CTRL_SPI_CSEN` ^| r/w <| Allow SPI chip-select to be actually asserted when set + <|`22` `XIP_CTRL_HIGHSPEED` ^| r/w <| enable SPI high-speed mode (ignoring _XIP_CTRL_PRSC_) + <|`23` `XIP_CTRL_BURST_EN` ^| r/w <| Enable XIP burst mode <|`29:28` - ^| r/- <| _reserved_, read as zero <|`30` `XIP_CTRL_PHY_BUSY` ^| r/- <| SPI PHY busy when set <|`31` `XIP_CTRL_XIP_BUSY` ^| r/- <| XIP access in progress when set diff --git a/docs/datasheet/soc_xirq.adoc b/docs/datasheet/soc_xirq.adoc index 44e350a2d..f163d82c4 100644 --- a/docs/datasheet/soc_xirq.adoc +++ b/docs/datasheet/soc_xirq.adoc @@ -71,8 +71,8 @@ In order to acknowledge an XIRQ interrupt, the interrupt handler has to... [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s) | R/W | Description -| `0xffffff80` | `EIE` | `31:0` | r/w | External interrupt enable register (one bit per channel, LSB-aligned) -| `0xffffff84` | `EIP` | `31:0` | r/w | External interrupt pending register (one bit per channel, LSB-aligned); writing 0 to a bit clears the according pending interrupt -| `0xffffff88` | `ESC` | `4:0` | r/w | Interrupt source ID (0..31) of firing IRQ (prioritized!); writing _any_ value will acknowledge the current XIRQ interrupt -| `0xffffff8c` | - | `31:0` | r/- | _reserved_, read as zero +| `0xfffff300` | `EIE` | `31:0` | r/w | External interrupt enable register (one bit per channel, LSB-aligned) +| `0xfffff304` | `EIP` | `31:0` | r/w | External interrupt pending register (one bit per channel, LSB-aligned); writing 0 to a bit clears the according pending interrupt +| `0xfffff308` | `ESC` | `4:0` | r/w | Interrupt source ID (0..31) of firing IRQ (prioritized!); writing _any_ value will acknowledge the current XIRQ interrupt +| `0xfffff30c` | - | `31:0` | r/- | _reserved_, read as zero |======================= diff --git a/docs/datasheet/software.adoc b/docs/datasheet/software.adoc index be41b583e..68a9e90c3 100644 --- a/docs/datasheet/software.adoc +++ b/docs/datasheet/software.adoc @@ -293,7 +293,7 @@ and packed into a final executable. After all the application sources have been compiled, they need to be _linked_. For this purpose the makefile uses the NEORV32-specific linker script `sw/common/neorv32.ld` for linking all object files that were generated during compilation. In general, the linker script defines -three memory sections: `rom`, `ram` and `iodev`. +two final memory sections: `rom` and `ram`. .Linker script - memory sections [cols="<2,<8"] @@ -302,12 +302,8 @@ three memory sections: `rom`, `ram` and `iodev`. | Memory section | Description | `ram` | Data memory address space (processor-internal/external DMEM) | `rom` | Instruction memory address space (processor-internal/external IMEM) _or_ internal bootloader ROM -| `iodev` | Processor-internal memory-mapped IO/peripheral devices address space |======================= -[NOTE] -The `iodev` section is entirely defined by the processor hardware layout and should not be modified at all. - [NOTE] The `rom` section is automatically re-mapped to the processor-internal <<_bootloader_rom_bootrom>> when (re-)compiling the bootloader @@ -322,7 +318,7 @@ while `LENGTH` defines its size in bytes. The attributes are configured indirect __neorv32_rom_size = DEFINED(__neorv32_rom_size) ? __neorv32_rom_size : 2048M; __neorv32_ram_size = DEFINED(__neorv32_ram_size) ? __neorv32_ram_size : 8K; -/* Default section base addresses - do not change this unless the hardware-defined address space layout is changed! */ +/* Default section base addresses */ __neorv32_rom_base = DEFINED(__neorv32_rom_base) ? __neorv32_rom_base : 0x00000000; /* = VHDL package's "ispace_base_c" */ __neorv32_ram_base = DEFINED(__neorv32_ram_base) ? __neorv32_ram_base : 0x80000000; /* = VHDL package's "dspace_base_c" */ ---- @@ -330,7 +326,7 @@ __neorv32_ram_base = DEFINED(__neorv32_ram_base) ? __neorv32_ram_base : 0x800000 The region size and base address configuration can be edited by the user - either by explicitly changing the default values in the linker script or by overriding them when invoking `make`: -.Overriding default rom size configuration (setting 4096 bytes) +.Overriding default `rom` size configuration (configuring 4096 bytes) [source, bash] ---- $ make USER_FLAGS+="-Wl,--defsym,__neorv32_rom_size=4096" clean_all exe @@ -377,8 +373,8 @@ section and to clear the `.bss` section (faster!). :sectnums: ==== RAM Layout -The default NEORV32 linker script uses all of the defined RAM (linker script memory section `ram`) to create four areas. -Note that depending on the application some areas might not be existent at all. +The default NEORV32 linker script uses all of the defined RAM (linker script memory section `ram`) to several sections. +Note that depending on the application some sections might have zero size. .Default RAM Layout image::ram_layout.png[400] diff --git a/docs/figures/address_space.png b/docs/figures/address_space.png index b358eee95..8fd7c23e3 100644 Binary files a/docs/figures/address_space.png and b/docs/figures/address_space.png differ diff --git a/docs/figures/neorv32_bus.png b/docs/figures/neorv32_bus.png index 2c1b9c86f..1edd41315 100644 Binary files a/docs/figures/neorv32_bus.png and b/docs/figures/neorv32_bus.png differ diff --git a/docs/figures/neorv32_memory_configurations.png b/docs/figures/neorv32_memory_configurations.png deleted file mode 100644 index 85cf1fbde..000000000 Binary files a/docs/figures/neorv32_memory_configurations.png and /dev/null differ diff --git a/docs/userguide/customizing_the_bootloader.adoc b/docs/userguide/customizing_the_bootloader.adoc index 8dc3496be..c4dfec948 100644 --- a/docs/userguide/customizing_the_bootloader.adoc +++ b/docs/userguide/customizing_the_bootloader.adoc @@ -37,7 +37,6 @@ minimal base + privileged ISA `rv32i_zicsr` only to ensure it can work independe | `SPI_BOOT_BASE_ADDR` | `0x00400000` | _any_ 32-bit value | Defines the _base_ address of the executable in external flash 4+^| XIP configuration | `XIP_EN` | `0` | `0`, `1` | Set `1` to enable the XIP options -| `XIP_PAGE_BASE_ADDR` | `0x40000000` | _any_ 32-bit value | Defines the page _base_ address where the XP flash will be mapped to |======================= [NOTE] diff --git a/rtl/core/mem/neorv32_dmem.default.vhd b/rtl/core/mem/neorv32_dmem.default.vhd index 604456eb9..f08b7b9d9 100644 --- a/rtl/core/mem/neorv32_dmem.default.vhd +++ b/rtl/core/mem/neorv32_dmem.default.vhd @@ -41,15 +41,10 @@ use neorv32.neorv32_package.all; architecture neorv32_dmem_rtl of neorv32_dmem is - -- IO space: module base address -- - constant hi_abb_c : natural := 31; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(DMEM_SIZE); -- low address boundary bit - -- local signals -- - signal acc_en : std_ulogic; - signal rdata : std_ulogic_vector(31 downto 0); - signal rden : std_ulogic; - signal addr : std_ulogic_vector(index_size_f(DMEM_SIZE/4)-1 downto 0); + signal rdata : std_ulogic_vector(31 downto 0); + signal rden : std_ulogic; + signal addr : std_ulogic_vector(index_size_f(DMEM_SIZE/4)-1 downto 0); -- -------------------------------------------------------------------------------------------------------------- -- -- The memory (RAM) is built from 4 individual byte-wide memories b0..b3, since some synthesis tools have -- @@ -80,8 +75,7 @@ begin -- Access Control ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = DMEM_BASE(hi_abb_c downto lo_abb_c)) else '0'; - addr <= bus_req_i.addr(index_size_f(DMEM_SIZE/4)+1 downto 2); -- word aligned + addr <= bus_req_i.addr(index_size_f(DMEM_SIZE/4)+1 downto 2); -- word aligned -- Memory Access -------------------------------------------------------------------------- @@ -89,16 +83,16 @@ begin mem_access: process(clk_i) begin if rising_edge(clk_i) then - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(0) = '1') then -- byte 0 + if (bus_req_i.we = '1') and (bus_req_i.ben(0) = '1') then -- byte 0 mem_ram_b0(to_integer(unsigned(addr))) <= bus_req_i.data(07 downto 00); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(1) = '1') then -- byte 1 + if (bus_req_i.we = '1') and (bus_req_i.ben(1) = '1') then -- byte 1 mem_ram_b1(to_integer(unsigned(addr))) <= bus_req_i.data(15 downto 08); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(2) = '1') then -- byte 2 + if (bus_req_i.we = '1') and (bus_req_i.ben(2) = '1') then -- byte 2 mem_ram_b2(to_integer(unsigned(addr))) <= bus_req_i.data(23 downto 16); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(3) = '1') then -- byte 3 + if (bus_req_i.we = '1') and (bus_req_i.ben(3) = '1') then -- byte 3 mem_ram_b3(to_integer(unsigned(addr))) <= bus_req_i.data(31 downto 24); end if; mem_ram_b0_rd <= mem_ram_b0(to_integer(unsigned(addr))); @@ -114,8 +108,8 @@ begin bus_feedback: process(clk_i) begin if rising_edge(clk_i) then - rden <= acc_en and bus_req_i.re; - bus_rsp_o.ack <= acc_en and (bus_req_i.re or bus_req_i.we); + rden <= bus_req_i.re; + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; end if; end process bus_feedback; diff --git a/rtl/core/mem/neorv32_dmem.legacy.vhd b/rtl/core/mem/neorv32_dmem.legacy.vhd index 990fbdbb9..fb105df30 100644 --- a/rtl/core/mem/neorv32_dmem.legacy.vhd +++ b/rtl/core/mem/neorv32_dmem.legacy.vhd @@ -41,12 +41,7 @@ use neorv32.neorv32_package.all; architecture neorv32_dmem_rtl of neorv32_dmem is - -- IO space: module base address -- - constant hi_abb_c : natural := 31; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(DMEM_SIZE); -- low address boundary bit - -- local signals -- - signal acc_en : std_ulogic; signal rdata : std_ulogic_vector(31 downto 0); signal rden : std_ulogic; signal addr : std_ulogic_vector(index_size_f(DMEM_SIZE/4)-1 downto 0); @@ -81,8 +76,7 @@ begin -- Access Control ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = DMEM_BASE(hi_abb_c downto lo_abb_c)) else '0'; - addr <= bus_req_i.addr(index_size_f(DMEM_SIZE/4)+1 downto 2); -- word aligned + addr <= bus_req_i.addr(index_size_f(DMEM_SIZE/4)+1 downto 2); -- word aligned -- Memory Access -------------------------------------------------------------------------- @@ -91,16 +85,16 @@ begin begin if rising_edge(clk_i) then addr_ff <= addr; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(0) = '1') then -- byte 0 + if (bus_req_i.we = '1') and (bus_req_i.ben(0) = '1') then -- byte 0 mem_ram_b0(to_integer(unsigned(addr))) <= bus_req_i.data(07 downto 00); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(1) = '1') then -- byte 1 + if (bus_req_i.we = '1') and (bus_req_i.ben(1) = '1') then -- byte 1 mem_ram_b1(to_integer(unsigned(addr))) <= bus_req_i.data(15 downto 08); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(2) = '1') then -- byte 2 + if (bus_req_i.we = '1') and (bus_req_i.ben(2) = '1') then -- byte 2 mem_ram_b2(to_integer(unsigned(addr))) <= bus_req_i.data(23 downto 16); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(3) = '1') then -- byte 3 + if (bus_req_i.we = '1') and (bus_req_i.ben(3) = '1') then -- byte 3 mem_ram_b3(to_integer(unsigned(addr))) <= bus_req_i.data(31 downto 24); end if; end if; @@ -118,8 +112,8 @@ begin bus_feedback: process(clk_i) begin if rising_edge(clk_i) then - rden <= acc_en and bus_req_i.re; - bus_rsp_o.ack <= acc_en and (bus_req_i.re or bus_req_i.we); + rden <= bus_req_i.re; + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; end if; end process bus_feedback; diff --git a/rtl/core/mem/neorv32_imem.default.vhd b/rtl/core/mem/neorv32_imem.default.vhd index 4d35dec10..5a7613b78 100644 --- a/rtl/core/mem/neorv32_imem.default.vhd +++ b/rtl/core/mem/neorv32_imem.default.vhd @@ -45,15 +45,10 @@ use neorv32.neorv32_application_image.all; -- this file is generated by the imag architecture neorv32_imem_rtl of neorv32_imem is - -- IO space: module base address -- - constant hi_abb_c : natural := 31; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(IMEM_SIZE); -- low address boundary bit - -- local signals -- - signal acc_en : std_ulogic; - signal rdata : std_ulogic_vector(31 downto 0); - signal rden : std_ulogic; - signal addr : std_ulogic_vector(index_size_f(IMEM_SIZE/4)-1 downto 0); + signal rdata : std_ulogic_vector(31 downto 0); + signal rden : std_ulogic; + signal addr : std_ulogic_vector(index_size_f(IMEM_SIZE/4)-1 downto 0); -- --------------------------- -- -- IMEM as pre-initialized ROM -- @@ -105,8 +100,7 @@ begin -- Access Control ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = IMEM_BASE(hi_abb_c downto lo_abb_c)) else '0'; - addr <= bus_req_i.addr(index_size_f(IMEM_SIZE/4)+1 downto 2); -- word aligned + addr <= bus_req_i.addr(index_size_f(IMEM_SIZE/4)+1 downto 2); -- word aligned -- Implement IMEM as pre-initialized ROM -------------------------------------------------- @@ -116,9 +110,7 @@ begin mem_access: process(clk_i) begin if rising_edge(clk_i) then - if (acc_en = '1') then -- reduce switching activity when not accessed - mem_rom_rd <= mem_rom(to_integer(unsigned(addr))); - end if; + mem_rom_rd <= mem_rom(to_integer(unsigned(addr))); end if; end process mem_access; -- read data -- @@ -133,16 +125,16 @@ begin mem_access: process(clk_i) begin if rising_edge(clk_i) then - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(0) = '1') then -- byte 0 + if (bus_req_i.we = '1') and (bus_req_i.ben(0) = '1') then -- byte 0 mem_ram_b0(to_integer(unsigned(addr))) <= bus_req_i.data(07 downto 00); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(1) = '1') then -- byte 1 + if (bus_req_i.we = '1') and (bus_req_i.ben(1) = '1') then -- byte 1 mem_ram_b1(to_integer(unsigned(addr))) <= bus_req_i.data(15 downto 08); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(2) = '1') then -- byte 2 + if (bus_req_i.we = '1') and (bus_req_i.ben(2) = '1') then -- byte 2 mem_ram_b2(to_integer(unsigned(addr))) <= bus_req_i.data(23 downto 16); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(3) = '1') then -- byte 3 + if (bus_req_i.we = '1') and (bus_req_i.ben(3) = '1') then -- byte 3 mem_ram_b3(to_integer(unsigned(addr))) <= bus_req_i.data(31 downto 24); end if; mem_b0_rd <= mem_ram_b0(to_integer(unsigned(addr))); @@ -161,12 +153,12 @@ begin bus_feedback: process(clk_i) begin if rising_edge(clk_i) then - rden <= acc_en and bus_req_i.re; + rden <= bus_req_i.re; if (IMEM_AS_IROM = true) then - bus_rsp_o.ack <= acc_en and bus_req_i.re; - bus_rsp_o.err <= acc_en and bus_req_i.we; + bus_rsp_o.ack <= bus_req_i.re; + bus_rsp_o.err <= bus_req_i.we; else - bus_rsp_o.ack <= acc_en and (bus_req_i.re or bus_req_i.we); + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; bus_rsp_o.err <= '0'; end if; end if; diff --git a/rtl/core/mem/neorv32_imem.legacy.vhd b/rtl/core/mem/neorv32_imem.legacy.vhd index 295977ebd..47ee36d75 100644 --- a/rtl/core/mem/neorv32_imem.legacy.vhd +++ b/rtl/core/mem/neorv32_imem.legacy.vhd @@ -45,12 +45,7 @@ use neorv32.neorv32_application_image.all; -- this file is generated by the imag architecture neorv32_imem_rtl of neorv32_imem is - -- IO space: module base address -- - constant hi_abb_c : natural := 31; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(IMEM_SIZE); -- low address boundary bit - -- local signals -- - signal acc_en : std_ulogic; signal rdata : std_ulogic_vector(31 downto 0); signal rden : std_ulogic; signal addr : std_ulogic_vector(index_size_f(IMEM_SIZE/4)-1 downto 0); @@ -106,8 +101,7 @@ begin -- Access Control ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = IMEM_BASE(hi_abb_c downto lo_abb_c)) else '0'; - addr <= bus_req_i.addr(index_size_f(IMEM_SIZE/4)+1 downto 2); -- word aligned + addr <= bus_req_i.addr(index_size_f(IMEM_SIZE/4)+1 downto 2); -- word aligned -- Implement IMEM as pre-initialized ROM -------------------------------------------------- @@ -117,9 +111,7 @@ begin mem_access: process(clk_i) begin if rising_edge(clk_i) then - if (acc_en = '1') then -- reduce switching activity when not accessed - mem_rom_rd <= mem_rom(to_integer(unsigned(addr))); - end if; + mem_rom_rd <= mem_rom(to_integer(unsigned(addr))); end if; end process mem_access; -- read data -- @@ -135,16 +127,16 @@ begin begin if rising_edge(clk_i) then addr_ff <= addr; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(0) = '1') then -- byte 0 + if (bus_req_i.we = '1') and (bus_req_i.ben(0) = '1') then -- byte 0 mem_ram_b0(to_integer(unsigned(addr))) <= bus_req_i.data(07 downto 00); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(1) = '1') then -- byte 1 + if (bus_req_i.we = '1') and (bus_req_i.ben(1) = '1') then -- byte 1 mem_ram_b1(to_integer(unsigned(addr))) <= bus_req_i.data(15 downto 08); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(2) = '1') then -- byte 2 + if (bus_req_i.we = '1') and (bus_req_i.ben(2) = '1') then -- byte 2 mem_ram_b2(to_integer(unsigned(addr))) <= bus_req_i.data(23 downto 16); end if; - if (acc_en = '1') and (bus_req_i.we = '1') and (bus_req_i.ben(3) = '1') then -- byte 3 + if (bus_req_i.we = '1') and (bus_req_i.ben(3) = '1') then -- byte 3 mem_ram_b3(to_integer(unsigned(addr))) <= bus_req_i.data(31 downto 24); end if; end if; @@ -164,12 +156,12 @@ begin bus_feedback: process(clk_i) begin if rising_edge(clk_i) then - rden <= acc_en and bus_req_i.re; + rden <= bus_req_i.re; if (IMEM_AS_IROM = true) then - bus_rsp_o.ack <= acc_en and bus_req_i.re; - bus_rsp_o.err <= acc_en and bus_req_i.we; + bus_rsp_o.ack <= bus_req_i.re; + bus_rsp_o.err <= bus_req_i.we; else - bus_rsp_o.ack <= acc_en and (bus_req_i.re or bus_req_i.we); + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; bus_rsp_o.err <= '0'; end if; end if; diff --git a/rtl/core/neorv32_application_image.vhd b/rtl/core/neorv32_application_image.vhd index babd71b6b..aac037428 100644 --- a/rtl/core/neorv32_application_image.vhd +++ b/rtl/core/neorv32_application_image.vhd @@ -1,8 +1,8 @@ -- The NEORV32 RISC-V Processor: https://github.com/stnolting/neorv32 -- Auto-generated memory initialization file (for APPLICATION) from source file --- Size: 1092 bytes +-- Size: 1096 bytes -- MARCH: default --- Built: 02.06.2023 11:53:17 +-- Built: 15.07.2023 21:10:26 -- prototype defined in 'neorv32_package.vhd' package body neorv32_application_image is @@ -39,7 +39,7 @@ x"00000e13", x"00000e93", x"00000f13", x"00000f93", -x"44400593", +x"44800593", x"80000617", x"f8060613", x"80000697", @@ -60,9 +60,9 @@ x"00072023", x"00470713", x"ff5ff06f", x"00000417", -x"37840413", +x"37c40413", x"00000497", -x"37048493", +x"37448493", x"00945a63", x"00042083", x"000080e7", @@ -74,9 +74,9 @@ x"090000ef", x"30401073", x"34051073", x"00000417", -x"34040413", +x"34440413", x"00000497", -x"33848493", +x"33c48493", x"00945a63", x"00042083", x"000080e7", @@ -111,19 +111,20 @@ x"00000513", x"00000593", x"00112623", x"00812423", -x"134000ef", +x"138000ef", x"00000513", x"00150413", x"00000593", x"0ff57513", -x"120000ef", +x"124000ef", x"0fa00513", -x"034000ef", +x"038000ef", x"00040513", x"fe5ff06f", -x"f9402583", -x"f9002503", -x"f9402783", +x"fffff737", +x"40472583", +x"40072503", +x"40472783", x"fef59ae3", x"00008067", x"c80027f3", @@ -133,7 +134,7 @@ x"fef59ae3", x"00008067", x"fe010113", x"00a12623", -x"fe002503", +x"e0002503", x"3e800593", x"00112e23", x"00812c23", @@ -165,16 +166,16 @@ x"01812403", x"01412483", x"02010113", x"00008067", -x"fe802783", +x"e0802783", x"00020737", x"00e7f7b3", x"02078663", -x"f41ff0ef", +x"f3dff0ef", x"00850433", x"00a43533", x"009585b3", x"00b504b3", -x"f2dff0ef", +x"f29ff0ef", x"fe95eee3", x"fcb490e3", x"fe856ae3", @@ -188,7 +189,7 @@ x"fff40413", x"00000013", x"ff1ff06f", x"f95ff06f", -x"fc000793", +x"c0000793", x"00a7a423", x"00b7a623", x"00008067", diff --git a/rtl/core/neorv32_boot_rom.vhd b/rtl/core/neorv32_boot_rom.vhd index e15919e60..40b6236de 100644 --- a/rtl/core/neorv32_boot_rom.vhd +++ b/rtl/core/neorv32_boot_rom.vhd @@ -41,9 +41,6 @@ use neorv32.neorv32_package.all; use neorv32.neorv32_bootloader_image.all; -- this file is generated by the image generator entity neorv32_boot_rom is - generic ( - BOOTROM_BASE : std_ulogic_vector(31 downto 0) -- boot ROM base address - ); port ( clk_i : in std_ulogic; -- global clock line bus_req_i : in bus_req_t; -- bus request @@ -55,18 +52,11 @@ architecture neorv32_boot_rom_rtl of neorv32_boot_rom is -- determine required ROM size in bytes (expand to next power of two) -- constant boot_rom_size_index_c : natural := index_size_f((bootloader_init_image'length)); -- address with (32-bit entries) - constant boot_rom_size_c : natural := (2**boot_rom_size_index_c)*4; -- size in bytes - - -- IO space: module base address -- - constant hi_abb_c : natural := 31; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(boot_rom_max_size_c); -- low address boundary bit + constant boot_rom_size_c : natural := (2**boot_rom_size_index_c)*4; -- physical size in bytes -- local signals -- - signal acc_en : std_ulogic; - signal rden : std_ulogic; - signal wren : std_ulogic; - signal rdata : std_ulogic_vector(31 downto 0); - signal addr : std_ulogic_vector(boot_rom_size_index_c-1 downto 0); + signal rden : std_ulogic; + signal rdata : std_ulogic_vector(31 downto 0); -- ROM - initialized with executable code -- constant mem_rom : mem32_t(0 to boot_rom_size_c/4-1) := mem32_init_f(bootloader_init_image, boot_rom_size_c/4); @@ -75,17 +65,10 @@ begin -- Sanity Checks -------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - assert false report "NEORV32 PROCESSOR CONFIG NOTE: Implementing internal bootloader ROM (" & - natural'image(boot_rom_size_c) & " bytes)." severity note; - - assert not (boot_rom_size_c > boot_rom_max_size_c) report "NEORV32 PROCESSOR CONFIG ERROR! Boot ROM size out of range! Max " & - natural'image(boot_rom_max_size_c) & " bytes." severity error; - - - -- Access Control ------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = BOOTROM_BASE(hi_abb_c downto lo_abb_c)) else '0'; - addr <= bus_req_i.addr(boot_rom_size_index_c+1 downto 2); -- word aligned + assert false report + "NEORV32 PROCESSOR CONFIG NOTE: Implementing internal bootloader ROM (" & natural'image(boot_rom_size_c) & " bytes)." severity note; + assert not (boot_rom_size_c > mem_boot_size_c) report + "NEORV32 PROCESSOR CONFIG ERROR! Boot ROM size out of range! Max " & natural'image(mem_boot_size_c) & " bytes." severity error; -- Memory Access -------------------------------------------------------------------------- @@ -93,18 +76,15 @@ begin mem_file_access: process(clk_i) begin if rising_edge(clk_i) then - rden <= acc_en and bus_req_i.re; - wren <= acc_en and bus_req_i.we; - if (acc_en = '1') then -- reduce switching activity when not accessed - rdata <= mem_rom(to_integer(unsigned(addr))); - end if; + rden <= bus_req_i.re; + rdata <= mem_rom(to_integer(unsigned(bus_req_i.addr(boot_rom_size_index_c+1 downto 2)))); end if; end process mem_file_access; - -- output gate -- - bus_rsp_o.data <= rdata when (rden = '1') else (others => '0'); + -- response -- + bus_rsp_o.data <= rdata when (rden = '1') else (others => '0'); -- output gate bus_rsp_o.ack <= rden; - bus_rsp_o.err <= wren; + bus_rsp_o.err <= '0'; end neorv32_boot_rom_rtl; diff --git a/rtl/core/neorv32_bootloader_image.vhd b/rtl/core/neorv32_bootloader_image.vhd index 21b947905..2f680eeec 100644 --- a/rtl/core/neorv32_bootloader_image.vhd +++ b/rtl/core/neorv32_bootloader_image.vhd @@ -1,8 +1,8 @@ -- The NEORV32 RISC-V Processor: https://github.com/stnolting/neorv32 -- Auto-generated memory initialization file (for BOOTLOADER) from source file --- Size: 4064 bytes +-- Size: 4088 bytes -- MARCH: default --- Built: 02.06.2023 11:53:49 +-- Built: 15.07.2023 18:35:31 -- prototype defined in 'neorv32_package.vhd' package body neorv32_bootloader_image is @@ -13,9 +13,9 @@ x"30401073", x"00000097", x"0e008093", x"30509073", -x"80010117", +x"80004117", x"1e810113", -x"80010197", +x"80004197", x"7e418193", x"00000213", x"00000293", @@ -40,10 +40,10 @@ x"00000e93", x"00000f13", x"00000f93", x"00001597", -x"f6458593", -x"80010617", +x"f7c58593", +x"80004617", x"f7c60613", -x"80010697", +x"80004697", x"f7468693", x"00c58e63", x"00d65c63", @@ -52,7 +52,7 @@ x"00e62023", x"00458593", x"00460613", x"fedff06f", -x"80010717", +x"80004717", x"f5070713", x"80818793", x"00f75863", @@ -91,7 +91,7 @@ x"800004b7", x"0004a223", x"800007b7", x"0007a023", -x"ffff17b7", +x"ffffd7b7", x"04112623", x"04812423", x"05212023", @@ -104,282 +104,291 @@ x"03812423", x"03912223", x"03a12023", x"01b12e23", -x"a3478793", +x"a6c78793", x"30579073", -x"fe802783", +x"e0802783", x"00080737", x"00e7f7b3", x"00078863", -x"fa002423", +x"80002023", x"10100793", -x"faf02423", -x"fe802783", +x"80f02023", +x"e0802783", x"40000737", x"00e7f7b3", -x"06078863", -x"f4002023", -x"f4002423", -x"000067b7", -x"f4002623", -x"20578793", -x"f4f02023", -x"f4002423", -x"f4002623", -x"f4002783", -x"00e7f7b3", -x"fe079ce3", -x"f4002783", -x"02000737", -x"00e7e7b3", -x"f4f02023", -x"f4002783", -x"08000737", -x"00e7e7b3", -x"f4f02023", -x"f4002783", -x"fe1fe737", -x"43f70713", -x"00e7f7b3", -x"00801737", -x"60070713", -x"00e7e7b3", -x"f4f02023", -x"fe802783", +x"06078e63", +x"fffff737", +x"f0072023", +x"f0072423", +x"000066b7", +x"f0072623", +x"20568693", +x"f0d72023", +x"f0072423", +x"f0072623", +x"fffff7b7", +x"400006b7", +x"f007a703", +x"00d77733", +x"fe071ce3", +x"f007a703", +x"002006b7", +x"00d76733", +x"f0e7a023", +x"f007a703", +x"008006b7", +x"00d76733", +x"f0e7a023", +x"f007a703", +x"ffffe6b7", +x"43f68693", +x"00d77733", +x"000016b7", +x"60068693", +x"00d76733", +x"f0e7a023", +x"e0802783", x"00010737", x"00e7f7b3", x"00078863", x"00100793", -x"fcf02423", -x"fc002623", -x"fa002023", -x"fe002683", +x"c0f02423", +x"c0002623", +x"fffff7b7", +x"5007a023", +x"e0002683", x"00009737", x"ffff7637", x"00000793", x"5ff70713", x"a0060613", -x"20d76263", +x"20d76863", x"00000713", x"3fe00613", -x"20f66263", +x"20f66863", x"fff78793", x"000106b7", -x"00679793", x"fff68693", +x"00679793", x"00371713", -x"01877713", x"00d7f7b3", +x"01877713", x"00e7e7b3", x"0017e793", -x"faf02023", -x"fe802783", -x"00020737", -x"00e7f7b3", -x"02078663", -x"f8002823", -x"f8002a23", -x"fe002783", -x"0027d793", -x"f8f02c23", -x"f8002e23", +x"fffff737", +x"50f72023", +x"e0802783", +x"000206b7", +x"00d7f7b3", +x"02078863", +x"40072023", +x"40072223", +x"40070793", +x"e0002703", +x"00275713", +x"00e7a423", +x"0007a623", x"08000793", x"30479073", x"00800793", x"3007a073", -x"ffff1537", -x"dd850513", -x"6b0000ef", +x"ffffd537", +x"e0450513", +x"6d0000ef", x"f1302573", -x"634000ef", -x"ffff1537", -x"e1050513", -x"69c000ef", -x"fe402503", -x"620000ef", -x"ffff1537", -x"e1850513", -x"688000ef", -x"fe002503", -x"60c000ef", -x"ffff1537", -x"e2050513", -x"674000ef", +x"654000ef", +x"ffffd537", +x"e3c50513", +x"6bc000ef", +x"e0402503", +x"640000ef", +x"ffffd537", +x"e4450513", +x"6a8000ef", +x"e0002503", +x"62c000ef", +x"ffffd537", +x"e4c50513", +x"694000ef", x"30102573", -x"5f8000ef", -x"ffff1537", -x"e2850513", -x"660000ef", +x"618000ef", +x"ffffd537", +x"e5450513", +x"680000ef", x"fc002573", -x"5e4000ef", -x"ffff1537", -x"e3050513", -x"64c000ef", -x"fe802503", -x"ffff1437", -x"ffff1937", -x"5c8000ef", -x"ffff1537", -x"e3850513", -x"630000ef", -x"ff802503", -x"5b4000ef", -x"e4040513", -x"620000ef", -x"ff002503", -x"5a4000ef", -x"ffff1537", -x"e4c50513", +x"604000ef", +x"ffffd537", +x"e5c50513", +x"66c000ef", +x"e0802503", +x"ffffd437", +x"ffffd937", +x"5e8000ef", +x"ffffd537", +x"e6450513", +x"650000ef", +x"e1802503", +x"5d4000ef", +x"e6c40513", +x"640000ef", +x"e1002503", +x"5c4000ef", +x"ffffd537", +x"e7850513", +x"62c000ef", +x"e1c02503", +x"5b0000ef", +x"e6c40513", +x"61c000ef", +x"e1402503", +x"5a0000ef", +x"e0090513", x"60c000ef", -x"ffc02503", -x"590000ef", -x"e4040513", -x"5fc000ef", -x"ff402503", -x"580000ef", -x"dd490513", -x"5ec000ef", -x"fe802783", +x"e0802783", x"00020737", x"00e7f7b3", -x"04078c63", -x"ffff1537", -x"e5450513", -x"5d0000ef", -x"2bc000ef", -x"fe002403", -x"00040a37", -x"00010ab7", +x"04078e63", +x"ffffd537", +x"e8050513", +x"5f0000ef", +x"2c8000ef", +x"e0002403", +x"00040ab7", +x"fffffa37", x"00341413", x"00a409b3", x"0089b433", x"00b40433", -x"fe802783", -x"0147f7b3", -x"0a078663", -x"fa002783", +x"00010b37", +x"e0802783", x"0157f7b3", +x"0a078663", +x"500a2783", +x"0167f7b3", x"0a078063", -x"ffff1537", -x"fa402783", -x"e8050513", -x"588000ef", -x"ffff1a37", -x"e8ca0513", +x"ffffd537", +x"504a2783", +x"eac50513", +x"5a4000ef", +x"ffffda37", +x"eb8a0513", +x"598000ef", +x"fffffab7", +x"06c00b13", +x"07800c13", +x"07300c93", +x"ffffd7b7", +x"f3878513", x"57c000ef", -x"06c00a93", -x"07800b93", -x"07300c13", -x"06500c93", -x"ffff17b7", -x"f0c78513", -x"560000ef", -x"fa002783", -x"00010737", -x"00e7f7b3", +x"500aa783", +x"000106b7", +x"00d7f7b3", x"fe078ae3", -x"fa402403", +x"504aa403", x"0ff47413", x"00040513", -x"4b4000ef", -x"dd490513", -x"538000ef", +x"4cc000ef", +x"e0090513", +x"554000ef", x"07200793", x"06f41063", -x"ffff02b7", +x"ffffc2b7", x"00028067", x"00c686b3", x"00178793", -x"df5ff06f", +x"de9ff06f", x"ffe70693", x"ffd6f693", x"00069863", x"0037d793", x"00170713", -x"de9ff06f", +x"dddff06f", x"0017d793", x"ff5ff06f", -x"1e8000ef", +x"1f0000ef", x"f485e4e3", x"00b41463", x"f53560e3", x"00100513", -x"718000ef", -x"dd490513", -x"4dc000ef", +x"738000ef", +x"e0090513", +x"4f8000ef", x"00000513", -x"069000ef", -x"19540863", -x"028ae463", -x"19940863", +x"089000ef", +x"19640c63", +x"028b6663", +x"06500793", +x"18f40a63", x"06800793", -x"e8ca0513", +x"eb8a0513", x"02f40c63", x"03f00793", -x"18f40c63", -x"ffff1537", -x"fb050513", +x"18f40e63", +x"ffffd537", +x"fc850513", x"0240006f", x"07500793", x"02f40263", -x"17740c63", -x"ff8414e3", +x"17840e63", +x"ff9414e3", x"0044a403", x"02041063", -x"ffff1537", -x"f1450513", -x"484000ef", -x"f19ff06f", +x"ffffd537", +x"f4050513", +x"49c000ef", +x"f15ff06f", x"00000513", -x"6ac000ef", -x"f0dff06f", -x"ffff1537", -x"f3050513", -x"468000ef", +x"6c8000ef", +x"f09ff06f", +x"ffffd537", +x"f5c50513", +x"480000ef", x"00040513", -x"3ec000ef", -x"ffff1537", -x"f3850513", -x"454000ef", +x"404000ef", +x"ffffd537", +x"f6450513", +x"46c000ef", x"00400537", -x"3d8000ef", -x"ffff1537", -x"f5050513", -x"440000ef", -x"00010737", -x"fa002783", -x"00e7f7b3", +x"3f0000ef", +x"ffffd537", +x"f7c50513", +x"458000ef", +x"fffff737", +x"00010637", +x"50072783", +x"00c7f7b3", x"fe078ce3", -x"fa402983", +x"50472983", x"0ff9f993", x"00098513", -x"394000ef", +x"3a4000ef", x"07900793", -x"eaf998e3", -x"2a0000ef", +x"eaf994e3", +x"2b0000ef", x"00050663", x"00300513", -x"460000ef", -x"ffff1537", -x"f5c50513", -x"3fc000ef", -x"01045b13", +x"474000ef", +x"ffffd537", +x"f8850513", +x"410000ef", +x"01045b93", x"004009b7", x"00010db7", x"fff00d13", -x"220000ef", -x"150000ef", +x"230000ef", +x"154000ef", x"0d800513", -x"0f4000ef", +x"0f8000ef", x"00098513", -x"104000ef", -x"0d4000ef", -x"224000ef", +x"108000ef", +x"0d8000ef", +x"234000ef", x"00157513", x"fe051ce3", -x"fffb0b13", +x"fffb8b93", x"01b989b3", -x"fdab18e3", -x"ff002683", +x"fdab98e3", +x"e1002683", x"004009b7", x"00000d13", x"00000d93", @@ -389,7 +398,7 @@ x"00072583", x"00fd0533", x"00d12623", x"00bd8db3", -x"26c000ef", +x"27c000ef", x"004007b7", x"004d0d13", x"00c12683", @@ -398,42 +407,43 @@ x"fc8d6ce3", x"4788d5b7", x"afe58593", x"00400537", -x"248000ef", +x"258000ef", x"00040593", x"00498513", -x"23c000ef", +x"24c000ef", x"00898513", x"41b005b3", -x"230000ef", -x"ffff1537", -x"dbc50513", -x"ec1ff06f", +x"240000ef", +x"ffffd537", +x"de850513", +x"ebdff06f", x"00100513", -x"ec5ff06f", +x"ec1ff06f", x"0044a783", -x"e4079ee3", -x"ffff1537", -x"f6c50513", -x"ea5ff06f", +x"e4079ae3", +x"ffffd537", +x"f9850513", +x"ea1ff06f", x"00100513", -x"e4dff06f", -x"ffff1537", -x"f7c50513", -x"e91ff06f", -x"f9402583", -x"f9002503", -x"f9402783", +x"e45ff06f", +x"ffffd537", +x"fa850513", +x"e8dff06f", +x"fffff737", +x"40472583", +x"40072503", +x"40472783", x"fef59ae3", x"00008067", -x"fa800713", +x"80000713", x"00072783", x"fbf7f793", x"00f72023", x"00008067", -x"faa02623", -x"fa802783", +x"80a02223", +x"80002783", x"fe07cee3", -x"fac02503", +x"80402503", x"0ff57513", x"00008067", x"ff010113", @@ -451,7 +461,7 @@ x"00812403", x"00c12083", x"01010113", x"fb1ff06f", -x"fa800713", +x"80000713", x"00072783", x"f877f793", x"0407e793", @@ -463,24 +473,26 @@ x"03212023", x"01312e23", x"01412c23", x"01512a23", +x"01612823", x"02112623", x"02812423", x"00050913", x"00058993", x"00000493", -x"00010ab7", -x"00400a13", -x"04091a63", -x"fa002783", -x"0157f7b3", +x"fffffa37", +x"00010b37", +x"00400a93", +x"04091c63", +x"500a2783", +x"0167f7b3", x"fe078ce3", -x"fa402403", +x"504a2403", x"0ff47413", x"00c10793", x"009787b3", x"00878023", x"00148493", -x"fd449ce3", +x"fd549ce3", x"02c12083", x"02812403", x"00c12503", @@ -489,55 +501,56 @@ x"02012903", x"01c12983", x"01812a03", x"01412a83", +x"01012b03", x"03010113", x"00008067", -x"f61ff0ef", +x"f55ff0ef", x"00300513", x"00998433", -x"f01ff0ef", +x"ef5ff0ef", x"00040513", -x"f11ff0ef", +x"f05ff0ef", x"00000513", -x"ef1ff0ef", +x"ee5ff0ef", x"00050413", -x"ed5ff0ef", -x"f9dff06f", +x"ec9ff0ef", +x"f99ff06f", x"ff010113", x"00112623", -x"f2dff0ef", +x"f21ff0ef", x"00600513", -x"ed1ff0ef", +x"ec5ff0ef", x"00c12083", x"01010113", -x"eb1ff06f", +x"ea5ff06f", x"fe010113", x"00112e23", -x"f0dff0ef", +x"f01ff0ef", x"00500513", -x"eb1ff0ef", +x"ea5ff0ef", x"00000513", -x"ea9ff0ef", +x"e9dff0ef", x"00a12623", -x"e8dff0ef", +x"e81ff0ef", x"01c12083", x"00c12503", x"02010113", x"00008067", x"ff010113", x"00112623", -x"ed9ff0ef", +x"ecdff0ef", x"0ab00513", -x"e7dff0ef", -x"e65ff0ef", +x"e71ff0ef", +x"e59ff0ef", x"f95ff0ef", x"fb1ff0ef", x"00257793", x"fff00513", x"02078063", -x"eb5ff0ef", +x"ea9ff0ef", x"00400513", -x"e59ff0ef", -x"e41ff0ef", +x"e4dff0ef", +x"e35ff0ef", x"f91ff0ef", x"01e51513", x"41f55513", @@ -559,15 +572,15 @@ x"00c10793", x"008787b3", x"0007ca03", x"f21ff0ef", -x"e51ff0ef", +x"e45ff0ef", x"00200513", -x"df5ff0ef", +x"de9ff0ef", x"00848933", x"00090513", -x"e01ff0ef", +x"df5ff0ef", x"000a0513", -x"de1ff0ef", -x"dc9ff0ef", +x"dd5ff0ef", +x"dbdff0ef", x"f19ff0ef", x"00157513", x"fe051ce3", @@ -581,11 +594,12 @@ x"01c12983", x"01812a03", x"03010113", x"00008067", -x"00200737", -x"fa002783", -x"00e7f7b3", +x"fffff737", +x"00200637", +x"50072783", +x"00c7f7b3", x"fe079ce3", -x"faa02223", +x"50a72223", x"00008067", x"fe010113", x"01212823", @@ -595,19 +609,19 @@ x"00112e23", x"00812c23", x"00912a23", x"01312623", -x"fc9ff0ef", +x"fc5ff0ef", x"07800513", -x"ffff14b7", -x"fbdff0ef", +x"ffffd4b7", +x"fb9ff0ef", x"01c00413", -x"fbc48493", +x"fd448493", x"ffc00993", x"008957b3", x"00f7f793", x"00f487b3", x"0007c503", x"ffc40413", -x"f99ff0ef", +x"f95ff0ef", x"ff3414e3", x"01c12083", x"01812403", @@ -634,32 +648,32 @@ x"01010113", x"00008067", x"01249663", x"00d00513", -x"f2dff0ef", +x"f29ff0ef", x"00048513", -x"f25ff0ef", +x"f21ff0ef", x"fc9ff06f", x"ff010113", x"00812423", x"00050413", -x"ffff1537", -x"d7450513", +x"ffffd537", +x"da050513", x"00112623", x"f91ff0ef", x"00241793", -x"ffff1537", +x"ffffd537", x"008787b3", -x"fcc50513", +x"fe450513", x"00f50533", x"f79ff0ef", x"00800793", x"3007b073", -x"fe802783", +x"e0802783", x"00010737", x"00e7f7b3", x"00078863", x"00100793", -x"fcf02423", -x"fc002623", +x"c0f02423", +x"c0002623", x"0000006f", x"fb010113", x"04112623", @@ -683,28 +697,29 @@ x"01f12423", x"342024f3", x"800007b7", x"00778793", -x"0af49663", -x"fe802783", +x"0af49863", +x"e0802783", x"00010737", x"00e7f7b3", x"00078863", -x"fc802783", +x"c0802783", x"0017c793", -x"fcf02423", -x"fe802783", +x"c0f02423", +x"e0802783", x"00020737", x"00e7f7b3", -x"02078863", -x"bb5ff0ef", -x"fe002783", -x"fff00713", -x"f8e02c23", +x"02078a63", +x"ba1ff0ef", +x"e0002783", +x"fffff737", +x"fff00693", x"0027d793", x"00a78533", x"00f537b3", +x"40d72423", x"00b787b3", -x"f8f02e23", -x"f8a02c23", +x"40f72623", +x"40a72423", x"00000013", x"03c12403", x"04c12083", @@ -732,28 +747,28 @@ x"800007b7", x"0007a783", x"00078663", x"00100513", -x"e89ff0ef", +x"e85ff0ef", x"34102473", -x"fe802783", +x"e0802783", x"00040737", x"00e7f7b3", x"04078263", -x"ffff1537", -x"d7c50513", -x"e11ff0ef", +x"ffffd537", +x"da850513", +x"e0dff0ef", x"00048513", -x"d95ff0ef", +x"d91ff0ef", x"02000513", -x"d75ff0ef", +x"d6dff0ef", x"00040513", -x"d85ff0ef", +x"d81ff0ef", x"02000513", -x"d65ff0ef", +x"d5dff0ef", x"34302573", -x"d75ff0ef", -x"ffff1537", -x"dd450513", -x"dddff0ef", +x"d71ff0ef", +x"ffffd537", +x"e0050513", +x"dd9ff0ef", x"00440413", x"34141073", x"f39ff06f", @@ -773,43 +788,43 @@ x"01812423", x"00fb2023", x"00050413", x"02051863", -x"ffff1537", -x"d8850513", -x"d85ff0ef", +x"ffffd537", +x"db450513", +x"d81ff0ef", x"004005b7", x"00040513", -x"afdff0ef", +x"ae9ff0ef", x"4788d7b7", x"afe78793", x"04f50863", x"00000513", x"0380006f", -x"ffff1537", -x"da850513", -x"d59ff0ef", +x"ffffd537", +x"dd450513", +x"d55ff0ef", x"00400537", -x"cddff0ef", -x"ffff1537", -x"db450513", -x"d45ff0ef", -x"fe802783", +x"cd9ff0ef", +x"ffffd537", +x"de050513", +x"d41ff0ef", +x"e0802783", x"00080737", x"00e7f7b3", x"00079663", x"00300513", -x"d85ff0ef", -x"bb5ff0ef", +x"d81ff0ef", +x"badff0ef", x"fa0502e3", x"ff1ff06f", x"004009b7", x"00498593", x"00040513", -x"a95ff0ef", +x"a81ff0ef", x"00050a13", x"00898593", x"00040513", -x"a85ff0ef", -x"ff002c03", +x"a71ff0ef", +x"e1002c03", x"00050a93", x"ffca7b93", x"00000913", @@ -820,9 +835,9 @@ x"05791c63", x"015484b3", x"00200513", x"fa0494e3", -x"ffff1537", -x"dbc50513", -x"cc9ff0ef", +x"ffffd537", +x"de850513", +x"cc5ff0ef", x"02c12083", x"02812403", x"800007b7", @@ -839,7 +854,7 @@ x"00812c03", x"03010113", x"00008067", x"00040513", -x"a09ff0ef", +x"9f5ff0ef", x"012c07b3", x"00a484b3", x"00a7a023", @@ -850,24 +865,20 @@ x"00112623", x"00812423", x"00800793", x"3007b073", -x"ff002403", +x"e1002403", x"00050463", -x"40400437", -x"ffff1537", -x"dc050513", -x"c45ff0ef", +x"e0400437", +x"ffffd537", +x"dec50513", +x"c41ff0ef", x"00040513", -x"bc9ff0ef", -x"ffff1537", -x"dd050513", -x"c31ff0ef", -x"fa002783", +x"bc5ff0ef", +x"ffffd537", +x"dfc50513", +x"c2dff0ef", +x"fffff737", +x"50072783", x"fe07cee3", -x"fc0027f3", -x"0027f793", -x"00078463", -x"0000100f", -x"0ff0000f", x"000400e7", x"52450a07", x"00005f52", @@ -903,8 +914,8 @@ x"72656461", x"0a3e3e20", x"444c420a", x"4a203a56", -x"20206e75", -x"30322032", +x"31206c75", +x"30322035", x"480a3332", x"203a5657", x"00000020", @@ -999,19 +1010,14 @@ x"65206f4e", x"75636578", x"6c626174", x"00002e65", -x"20296328", -x"53207962", -x"68706574", -x"4e206e61", -x"69746c6f", -x"670a676e", -x"75687469", -x"6f632e62", -x"74732f6d", -x"746c6f6e", -x"2f676e69", -x"726f656e", -x"00323376", +x"68746967", +x"632e6275", +x"732f6d6f", +x"6c6f6e74", +x"676e6974", +x"6f656e2f", +x"32337672", +x"00000000", x"61766e49", x"2064696c", x"00444d43", diff --git a/rtl/core/neorv32_bus_keeper.vhd b/rtl/core/neorv32_bus_keeper.vhd deleted file mode 100644 index 09a1c753e..000000000 --- a/rtl/core/neorv32_bus_keeper.vhd +++ /dev/null @@ -1,124 +0,0 @@ --- ################################################################################################# --- # << NEORV32 - Bus Keeper (BUSKEEPER) >> # --- # ********************************************************************************************* # --- # This unit monitors the processor-internal bus. If the accessed module does not respond within # --- # the defined number of cycles (VHDL package: max_proc_int_response_time_c) or issues an ERROR # --- # condition, the BUS KEEPER asserts the error signal to inform the CPU. # --- # ********************************************************************************************* # --- # BSD 3-Clause License # --- # # --- # Copyright (c) 2023, 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 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # --- ################################################################################################# - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library neorv32; -use neorv32.neorv32_package.all; - -entity neorv32_bus_keeper is - port ( - clk_i : in std_ulogic; -- global clock line - rstn_i : in std_ulogic; -- global reset, low-active, async - bus_req_i : in bus_req_t; -- monitor request bus - bus_rsp_i : in bus_rsp_t; -- monitor response bus - bus_err_o : out std_ulogic; -- signal bus error to CPU - bus_tmo_i : in std_ulogic; -- transfer timeout (external interface) - bus_ext_i : in std_ulogic; -- external bus access - bus_xip_i : in std_ulogic -- pending XIP access - ); -end neorv32_bus_keeper; - -architecture neorv32_bus_keeper_rtl of neorv32_bus_keeper is - - -- timeout counter size -- - constant cnt_width_c : natural := index_size_f(max_proc_int_response_time_c); - - -- controller -- - type ctrl_t is record - pending : std_ulogic; - timeout : std_ulogic_vector(cnt_width_c-1 downto 0); - bus_err : std_ulogic; - ignore : std_ulogic; - end record; - signal ctrl : ctrl_t; - -begin - - -- Sanity Check -------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - assert not (max_proc_int_response_time_c < 2) - report "NEORV32 PROCESSOR CONFIG ERROR! Processor-internal bus timeout has to >= 2." severity error; - - - -- Monitor -------------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - keeper_control: process(rstn_i, clk_i) - begin - if (rstn_i = '0') then - ctrl.pending <= '0'; - ctrl.bus_err <= '0'; - ctrl.timeout <= (others => '0'); - ctrl.ignore <= '0'; - elsif rising_edge(clk_i) then - -- defaults -- - ctrl.bus_err <= '0'; - -- bus idle -- - if (ctrl.pending = '0') then - ctrl.timeout <= std_ulogic_vector(to_unsigned(max_proc_int_response_time_c-1, cnt_width_c)); - ctrl.ignore <= '0'; - if (bus_req_i.re = '1') or (bus_req_i.we = '1') then - ctrl.pending <= '1'; - end if; - -- bus access pending -- - else - -- countdown timer -- - ctrl.timeout <= std_ulogic_vector(unsigned(ctrl.timeout) - 1); - -- bus keeper shall ignore internal timeout during this access (because it's "external") -- - ctrl.ignore <= ctrl.ignore or (bus_ext_i or bus_xip_i); - -- response check -- - if (bus_rsp_i.err = '1') or -- error termination by bus system - (bus_tmo_i = '1') or -- EXTERNAL access timeout - ((or_reduce_f(ctrl.timeout) = '0') and (ctrl.ignore = '0')) then -- INTERNAL access timeout - ctrl.bus_err <= '1'; - ctrl.pending <= '0'; - elsif (bus_rsp_i.ack = '1') then -- normal termination by bus system - ctrl.bus_err <= '0'; - ctrl.pending <= '0'; - end if; - end if; - end if; - end process keeper_control; - - -- signal bus error to CPU -- - bus_err_o <= ctrl.bus_err; - - -end neorv32_bus_keeper_rtl; diff --git a/rtl/core/neorv32_busswitch.vhd b/rtl/core/neorv32_busswitch.vhd deleted file mode 100644 index f2eecc66b..000000000 --- a/rtl/core/neorv32_busswitch.vhd +++ /dev/null @@ -1,225 +0,0 @@ --- ################################################################################################# --- # << NEORV32 - Bus Switch >> # --- # ********************************************************************************************* # --- # Allows to access a single peripheral bus ("p_bus") by two controller ports. Controller port A # --- # ("ca_bus") has priority over controller port B ("cb_bus"). # --- # ********************************************************************************************* # --- # BSD 3-Clause License # --- # # --- # Copyright (c) 2023, 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 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # --- ################################################################################################# - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -library neorv32; -use neorv32.neorv32_package.all; - -entity neorv32_busswitch is - generic ( - PORT_A_READ_ONLY : boolean; -- set if port A is read-only - PORT_B_READ_ONLY : boolean -- set if port B is read-only - ); - port ( - clk_i : in std_ulogic; -- global clock, rising edge - rstn_i : in std_ulogic; -- global reset, low-active, async - a_req_i : in bus_req_t; -- host port A: request bus - a_rsp_o : out bus_rsp_t; -- host port A: response bus - b_req_i : in bus_req_t; -- host port B: request bus - b_rsp_o : out bus_rsp_t; -- host port B: response bus - x_req_o : out bus_req_t; -- device port request bus - x_rsp_i : in bus_rsp_t -- device port response bus - ); -end neorv32_busswitch; - -architecture neorv32_busswitch_rtl of neorv32_busswitch is - - -- access requests -- - signal a_rd_req_buf, a_wr_req_buf : std_ulogic; - signal b_rd_req_buf, b_wr_req_buf : std_ulogic; - signal a_req_current, a_req_pending : std_ulogic; - signal b_req_current, b_req_pending : std_ulogic; - - -- internal bus lines -- - signal a_bus_ack, b_bus_ack : std_ulogic; - signal a_bus_err, b_bus_err : std_ulogic; - signal x_bus_we, x_bus_re : std_ulogic; - - -- access arbiter -- - type arbiter_state_t is (IDLE, A_BUSY, A_RETIRE, B_BUSY, B_RETIRE); - type arbiter_t is record - state : arbiter_state_t; - state_nxt : arbiter_state_t; - bus_sel : std_ulogic; - re_trig : std_ulogic; - we_trig : std_ulogic; - end record; - signal arbiter : arbiter_t; - -begin - - -- Access Arbiter ------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - arbiter_sync: process(rstn_i, clk_i) - begin - if (rstn_i = '0') then - arbiter.state <= IDLE; - a_rd_req_buf <= '0'; - a_wr_req_buf <= '0'; - b_rd_req_buf <= '0'; - b_wr_req_buf <= '0'; - elsif rising_edge(clk_i) then - arbiter.state <= arbiter.state_nxt; - -- port A requests -- - a_rd_req_buf <= (a_rd_req_buf or a_req_i.re) and (not (a_bus_err or a_bus_ack)); - a_wr_req_buf <= (a_wr_req_buf or a_req_i.we) and (not (a_bus_err or a_bus_ack)) and bool_to_ulogic_f(PORT_A_READ_ONLY = false); - -- port B requests -- - b_rd_req_buf <= (b_rd_req_buf or b_req_i.re) and (not (b_bus_err or b_bus_ack)); - b_wr_req_buf <= (b_wr_req_buf or b_req_i.we) and (not (b_bus_err or b_bus_ack)) and bool_to_ulogic_f(PORT_B_READ_ONLY = false); - end if; - end process arbiter_sync; - - -- any current requests? -- - a_req_current <= (a_req_i.re or a_req_i.we) when (PORT_A_READ_ONLY = false) else a_req_i.re; - b_req_current <= (b_req_i.re or b_req_i.we) when (PORT_B_READ_ONLY = false) else b_req_i.re; - - -- any pending requests? -- - a_req_pending <= (a_rd_req_buf or a_wr_req_buf) when (PORT_A_READ_ONLY = false) else a_rd_req_buf; - b_req_pending <= (b_rd_req_buf or b_wr_req_buf) when (PORT_B_READ_ONLY = false) else b_rd_req_buf; - - -- FSM -- - arbiter_comb: process(arbiter, a_req_current, b_req_current, a_req_pending, b_req_pending, - a_rd_req_buf, a_wr_req_buf, b_rd_req_buf, b_wr_req_buf, x_rsp_i) - begin - -- arbiter defaults -- - arbiter.state_nxt <= arbiter.state; - arbiter.bus_sel <= '0'; - arbiter.we_trig <= '0'; - arbiter.re_trig <= '0'; - - -- state machine -- - case arbiter.state is - - when IDLE => -- wait for requests - -- ------------------------------------------------------------ - if (a_req_current = '1') then -- current request from port A? - arbiter.bus_sel <= '0'; - arbiter.state_nxt <= A_BUSY; - elsif (a_req_pending = '1') then -- pending request from port A? - arbiter.bus_sel <= '0'; - arbiter.state_nxt <= A_RETIRE; - elsif (b_req_current = '1') then -- pending request from port B? - arbiter.bus_sel <= '1'; - arbiter.state_nxt <= B_BUSY; - elsif (b_req_pending = '1') then -- current request from port B? - arbiter.bus_sel <= '1'; - arbiter.state_nxt <= B_RETIRE; - end if; - - when A_BUSY => -- port A pending access - -- ------------------------------------------------------------ - arbiter.bus_sel <= '0'; -- access from port A - if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then --- [COMMENT NOTE] Direct return to IDLE to further promote port A access requests. --- if (b_req_pending = '1') or (b_req_current = '1') then -- any request from B? --- arbiter.state_nxt <= B_RETIRE; --- else - arbiter.state_nxt <= IDLE; --- end if; - end if; - - when A_RETIRE => -- retire port A pending access - -- ------------------------------------------------------------ - arbiter.bus_sel <= '0'; -- access from port A - arbiter.we_trig <= a_wr_req_buf; - arbiter.re_trig <= a_rd_req_buf; - arbiter.state_nxt <= A_BUSY; - - when B_BUSY => -- port B pending access - -- ------------------------------------------------------------ - arbiter.bus_sel <= '1'; -- access from port B - if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then - if (a_req_pending = '1') or (a_req_current = '1') then -- any request from A? - arbiter.state_nxt <= A_RETIRE; - else - arbiter.state_nxt <= IDLE; - end if; - end if; - - when B_RETIRE => -- retire port B pending access - -- ------------------------------------------------------------ - arbiter.bus_sel <= '1'; -- access from port B - arbiter.we_trig <= b_wr_req_buf; - arbiter.re_trig <= b_rd_req_buf; - arbiter.state_nxt <= B_BUSY; - - when others => -- undefined - -- ------------------------------------------------------------ - arbiter.state_nxt <= IDLE; - - end case; - end process arbiter_comb; - - - -- Peripheral Bus Switch ------------------------------------------------------------------ - -- ------------------------------------------------------------------------------------------- - x_req_o.addr <= a_req_i.addr when (arbiter.bus_sel = '0') else b_req_i.addr; - - x_req_o.data <= b_req_i.data when (PORT_A_READ_ONLY = true) else - a_req_i.data when (PORT_B_READ_ONLY = true) else - a_req_i.data when (arbiter.bus_sel = '0') else b_req_i.data; - - x_req_o.ben <= b_req_i.ben when (PORT_A_READ_ONLY = true) else - a_req_i.ben when (PORT_B_READ_ONLY = true) else - a_req_i.ben when (arbiter.bus_sel = '0') else b_req_i.ben; - - x_req_o.priv <= a_req_i.priv when (arbiter.bus_sel = '0') else b_req_i.priv; - x_req_o.src <= a_req_i.src when (arbiter.bus_sel = '0') else b_req_i.src; - - x_bus_we <= a_req_i.we when (arbiter.bus_sel = '0') else b_req_i.we; - x_bus_re <= a_req_i.re when (arbiter.bus_sel = '0') else b_req_i.re; - x_req_o.we <= x_bus_we or arbiter.we_trig; - x_req_o.re <= x_bus_re or arbiter.re_trig; - - a_rsp_o.data <= x_rsp_i.data; - b_rsp_o.data <= x_rsp_i.data; - - a_bus_ack <= x_rsp_i.ack when (arbiter.bus_sel = '0') else '0'; - b_bus_ack <= x_rsp_i.ack when (arbiter.bus_sel = '1') else '0'; - a_rsp_o.ack <= a_bus_ack; - b_rsp_o.ack <= b_bus_ack; - - a_bus_err <= x_rsp_i.err when (arbiter.bus_sel = '0') else '0'; - b_bus_err <= x_rsp_i.err when (arbiter.bus_sel = '1') else '0'; - a_rsp_o.err <= a_bus_err; - b_rsp_o.err <= b_bus_err; - - -end neorv32_busswitch_rtl; diff --git a/rtl/core/neorv32_cfs.vhd b/rtl/core/neorv32_cfs.vhd index c8b061fe1..1ab5daf07 100644 --- a/rtl/core/neorv32_cfs.vhd +++ b/rtl/core/neorv32_cfs.vhd @@ -67,18 +67,6 @@ end neorv32_cfs; architecture neorv32_cfs_rtl of neorv32_cfs is - -- IO space: module base address -- - -- WARNING: Do not modify the CFS base address or the CFS' occupied address - -- space as this might cause access collisions with other processor modules. - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(cfs_size_c); -- low address boundary bit - - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- default CFS interface registers -- type cfs_regs_t is array (0 to 3) of std_ulogic_vector(31 downto 0); -- just implement 4 registers for this example signal cfs_reg_wr : cfs_regs_t; -- interface registers for WRITE accesses @@ -86,15 +74,6 @@ architecture neorv32_cfs_rtl of neorv32_cfs is begin - -- Access Control ------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - -- This logic is required to handle the CPU accesses - DO NOT MODIFY! - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = cfs_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= cfs_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; -- only full-word write accesses are supported - rden <= acc_en and bus_req_i.re; -- read accesses always return a full 32-bit word - - -- CFS Generics --------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- -- In it's default version the CFS provides three configuration generics: @@ -210,33 +189,33 @@ begin -- transfer/access acknowledge -- -- default: required for the CPU to check the CFS is answering a bus read OR write request; -- all read and write accesses (to any cfs_reg, even if there is no according physical register implemented) will succeed. - bus_rsp_o.ack <= rden or wren; + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- write access -- - if (wren = '1') then -- full-word write access, high for one cycle if there is an actual write access - if (addr = cfs_reg0_addr_c) then -- make sure to use the internal "addr" signal for the read/write interface + if (bus_req_i.we = '1') then -- full-word write access, high for one cycle if there is an actual write access + if (bus_req_i.addr(7 downto 2) = "000000") then -- make sure to use the internal "addr" signal for the read/write interface cfs_reg_wr(0) <= bus_req_i.data; -- some physical register, for example: control register end if; - if (addr = cfs_reg1_addr_c) then + if (bus_req_i.addr(7 downto 2) = "000001") then cfs_reg_wr(1) <= bus_req_i.data; -- some physical register, for example: data in/out fifo end if; - if (addr = cfs_reg2_addr_c) then + if (bus_req_i.addr(7 downto 2) = "000010") then cfs_reg_wr(2) <= bus_req_i.data; -- some physical register, for example: command fifo end if; - if (addr = cfs_reg3_addr_c) then + if (bus_req_i.addr(7 downto 2) = "000011") then cfs_reg_wr(3) <= bus_req_i.data; -- some physical register, for example: status register end if; end if; -- read access -- bus_rsp_o.data <= (others => '0'); -- the output HAS TO BE ZERO if there is no actual read access - if (rden = '1') then -- the read access is always 32-bit wide, high for one cycle if there is an actual read access - case addr is -- make sure to use the internal 'addr' signal for the read/write interface - when cfs_reg0_addr_c => bus_rsp_o.data <= cfs_reg_rd(0); - when cfs_reg1_addr_c => bus_rsp_o.data <= cfs_reg_rd(1); - when cfs_reg2_addr_c => bus_rsp_o.data <= cfs_reg_rd(2); - when cfs_reg3_addr_c => bus_rsp_o.data <= cfs_reg_rd(3); - when others => bus_rsp_o.data <= (others => '0'); -- the remaining registers are not implemented and will read as zero + if (bus_req_i.re = '1') then -- the read access is always 32-bit wide, high for one cycle if there is an actual read access + case bus_req_i.addr(7 downto 2) is -- make sure to use the internal 'addr' signal for the read/write interface + when "000000" => bus_rsp_o.data <= cfs_reg_rd(0); + when "000001" => bus_rsp_o.data <= cfs_reg_rd(1); + when "000010" => bus_rsp_o.data <= cfs_reg_rd(2); + when "000011" => bus_rsp_o.data <= cfs_reg_rd(3); + when others => bus_rsp_o.data <= (others => '0'); -- the remaining registers are not implemented and will read as zero end case; end if; end if; diff --git a/rtl/core/neorv32_crc.vhd b/rtl/core/neorv32_crc.vhd index e41e65a69..2beee15c5 100644 --- a/rtl/core/neorv32_crc.vhd +++ b/rtl/core/neorv32_crc.vhd @@ -54,21 +54,12 @@ end neorv32_crc; architecture neorv32_crc_rtl of neorv32_crc is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(crc_size_c); -- low address boundary bit - -- interface register addresses -- constant mode_addr_c : std_ulogic_vector(1 downto 0) := "00"; -- r/w: mode register constant poly_addr_c : std_ulogic_vector(1 downto 0) := "01"; -- r/w: polynomial register constant data_addr_c : std_ulogic_vector(1 downto 0) := "10"; -- -/w: data register constant sreg_addr_c : std_ulogic_vector(1 downto 0) := "11"; -- r/w: CRC shift register - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- CRC core -- type crc_t is record mode : std_ulogic_vector(01 downto 0); @@ -88,10 +79,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = crc_base_c(hi_abb_c downto lo_abb_c)) else '0'; - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; -- write access -- write_access: process(rstn_i, clk_i) @@ -102,7 +89,7 @@ begin crc.data <= (others => '0'); we_ack <= (others => '0'); elsif rising_edge(clk_i) then - if (wren = '1') then + if (bus_req_i.we = '1') then if (bus_req_i.addr(3 downto 2) = mode_addr_c) then -- mode select crc.mode <= bus_req_i.data(01 downto 0); end if; @@ -114,7 +101,7 @@ begin end if; end if; -- delayed write ACK -- - we_ack <= we_ack(we_ack'left-1 downto 0) & wren; + we_ack <= we_ack(we_ack'left-1 downto 0) & bus_req_i.we; end if; end process write_access; @@ -123,8 +110,8 @@ begin begin if rising_edge(clk_i) then bus_rsp_o.data <= (others => '0'); - bus_rsp_o.ack <= we_ack(we_ack'left) or rden; - if (rden = '1') then + bus_rsp_o.ack <= we_ack(we_ack'left) or bus_req_i.re; + if (bus_req_i.re = '1') then case bus_req_i.addr(3 downto 2) is when mode_addr_c => bus_rsp_o.data(01 downto 0) <= crc.mode; -- mode select when poly_addr_c => bus_rsp_o.data(31 downto 0) <= crc.poly; -- polynomial @@ -147,13 +134,13 @@ begin crc.sreg <= (others => '0'); elsif rising_edge(clk_i) then -- arbitration -- - if (wren = '1') and (bus_req_i.addr(3 downto 2) = data_addr_c) then -- writing new data + if (bus_req_i.we = '1') and (bus_req_i.addr(3 downto 2) = data_addr_c) then -- writing new data crc.cnt <= "0111"; -- start with MSB elsif (crc.cnt(3) = '0') then -- not done yet? crc.cnt <= std_ulogic_vector(unsigned(crc.cnt) - 1); end if; -- computation -- - if (wren = '1') and (bus_req_i.addr(3 downto 2) = sreg_addr_c) then -- set start value + if (bus_req_i.we = '1') and (bus_req_i.addr(3 downto 2) = sreg_addr_c) then -- set start value crc.sreg <= bus_req_i.data; elsif (crc.cnt(3) = '0') then if (crc.msb = crc.data(to_integer(unsigned(crc.cnt(2 downto 0))))) then diff --git a/rtl/core/neorv32_debug_dm.vhd b/rtl/core/neorv32_debug_dm.vhd index db0315f31..47222af08 100644 --- a/rtl/core/neorv32_debug_dm.vhd +++ b/rtl/core/neorv32_debug_dm.vhd @@ -56,6 +56,9 @@ library neorv32; use neorv32.neorv32_package.all; entity neorv32_debug_dm is + generic ( + CPU_BASE_ADDR : std_ulogic_vector(31 downto 0) + ); port ( -- global control -- clk_i : in std_ulogic; -- global clock line @@ -82,6 +85,14 @@ end neorv32_debug_dm; architecture neorv32_debug_dm_rtl of neorv32_debug_dm is + -- ********************************************************** + -- DM Layout + -- ********************************************************** + constant dm_code_base_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(CPU_BASE_ADDR) + x"00"); -- base address of code ROM (park loop) + constant dm_pbuf_base_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(CPU_BASE_ADDR) + x"40"); -- base address of program buffer (PBUF) + constant dm_data_base_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(CPU_BASE_ADDR) + x"80"); -- base address of abstract data buffer (DATA) + constant dm_sreg_base_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(CPU_BASE_ADDR) + x"C0"); -- base address of status register (SREG) + -- ********************************************************** -- DMI Access -- ********************************************************** @@ -175,10 +186,6 @@ architecture neorv32_debug_dm_rtl of neorv32_debug_dm is -- CPU Bus Interface -- ********************************************************** - -- IO space: module base address -- - constant hi_abb_c : natural := 31; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(dm_size_c); -- low address boundary bit - -- status and control register - bits -- -- for write access we only care about the actual BYTE WRITE ACCESSES! -- constant sreg_halt_ack_c : natural := 0; -- -/w: CPU is halted in debug mode and waits in park loop @@ -192,25 +199,28 @@ architecture neorv32_debug_dm_rtl of neorv32_debug_dm is -- copied manually from 'sw/ocd-firmware/neorv32_debug_mem_code.vhd' -- type code_rom_file_t is array (0 to 15) of std_ulogic_vector(31 downto 0); constant code_rom_file : code_rom_file_t := ( - 00 => x"8c0001a3", + 00 => x"fc0001a3", 01 => x"00100073", 02 => x"7b241073", - 03 => x"8c000023", - 04 => x"8c204403", + 03 => x"fc000023", + 04 => x"fc204403", 05 => x"00041c63", - 06 => x"8c104403", + 06 => x"fc104403", 07 => x"fe0408e3", - 08 => x"8c8000a3", + 08 => x"fc8000a3", 09 => x"7b202473", 10 => x"7b200073", - 11 => x"8c000123", + 11 => x"fc000123", 12 => x"7b202473", 13 => x"0000100f", - 14 => x"84000067", + 14 => x"f4000067", 15 => x"00000073" ); - -- Debug Core Interface + -- access helpers -- + signal rden, wren : std_ulogic; + + -- Debug Core Interface -- type dci_t is record halt_ack : std_ulogic; -- CPU (re-)entered HALT state (single-shot) resume_req : std_ulogic; -- DM wants the CPU to resume when set @@ -225,12 +235,6 @@ architecture neorv32_debug_dm_rtl of neorv32_debug_dm is end record; signal dci : dci_t; - -- global access control -- - signal acc_en : std_ulogic; - signal rden : std_ulogic; - signal wren : std_ulogic; - signal maddr : std_ulogic_vector(01 downto 0); - -- data buffer -- signal data_buf : std_ulogic_vector(31 downto 0); @@ -310,7 +314,7 @@ begin dm_ctrl.ldsw_progbuf(11 downto 07) <= dataaddr_c(04 downto 00); -- destination address else -- "write" = 1 -> write to GPR dm_ctrl.ldsw_progbuf <= instr_lw_c; - dm_ctrl.ldsw_progbuf(31 downto 20) <= dataaddr_c; -- source address + dm_ctrl.ldsw_progbuf(31 downto 20) <= dataaddr_c(11 downto 00); -- source address dm_ctrl.ldsw_progbuf(11 downto 07) <= dm_reg.command(4 downto 0); -- "regno" = destination register end if; else @@ -602,7 +606,7 @@ begin dmi_rsp_data_o(19 downto 17) <= (others => '0'); -- reserved (r/-) dmi_rsp_data_o(16) <= dataaccess_c; -- dataaccess (r/-): 1: data registers are memory-mapped, 0: data reisters are CSR-mapped dmi_rsp_data_o(15 downto 12) <= datasize_c; -- datasize (r/-): number data registers in memory/CSR space - dmi_rsp_data_o(11 downto 00) <= dataaddr_c; -- dataaddr (r/-): data registers base address (memory/CSR) + dmi_rsp_data_o(11 downto 00) <= dataaddr_c(11 downto 0); -- dataaddr (r/-): data registers base address (memory/CSR) -- abstract control and status -- when addr_abstractcs_c => @@ -680,10 +684,8 @@ begin -- Access Control ------------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = dm_base_c(hi_abb_c downto lo_abb_c)) else '0'; - maddr <= bus_req_i.addr(lo_abb_c-1 downto lo_abb_c-2); -- (sub-)module select address - rden <= acc_en and cpu_debug_i and bus_req_i.re; -- allow access only when in debug mode - wren <= acc_en and cpu_debug_i and bus_req_i.we; -- allow access only when in debug mode + rden <= cpu_debug_i and bus_req_i.re; -- allow access only when in debug mode + wren <= cpu_debug_i and bus_req_i.we; -- allow access only when in debug mode -- Write Access --------------------------------------------------------------------------- @@ -700,7 +702,7 @@ begin -- data buffer -- if (dci.data_we = '1') then -- DM write access data_buf <= dci.wdata; - elsif (maddr = "10") and (wren = '1') then -- CPU write access + elsif (bus_req_i.addr(7 downto 6) = dm_data_base_c(7 downto 6)) and (wren = '1') then -- CPU write access data_buf <= bus_req_i.data; end if; -- control and status register CPU write access -- @@ -709,7 +711,7 @@ begin dci.resume_ack <= '0'; dci.execute_ack <= '0'; dci.exception_ack <= '0'; - if (maddr = "11") and (wren = '1') then + if (bus_req_i.addr(7 downto 6) = dm_sreg_base_c(7 downto 6)) and (wren = '1') then if (bus_req_i.ben(sreg_halt_ack_c/8) = '1') then dci.halt_ack <= '1'; end if; @@ -738,14 +740,14 @@ begin bus_rsp_o.ack <= rden or wren; bus_rsp_o.data <= (others => '0'); if (rden = '1') then -- output enable - case maddr is -- module select - when "00" => -- code ROM + case bus_req_i.addr(7 downto 6) is -- module select + when "00" => -- dm_code_base_c: code ROM bus_rsp_o.data <= code_rom_file(to_integer(unsigned(bus_req_i.addr(5 downto 2)))); - when "01" => -- program buffer + when "01" => -- dm_pbuf_base_c: program buffer bus_rsp_o.data <= cpu_progbuf(to_integer(unsigned(bus_req_i.addr(3 downto 2)))); - when "10" => -- data buffer + when "10" => -- dm_data_base_c: data buffer bus_rsp_o.data <= data_buf; - when others => -- control and status register + when others => -- dm_sreg_base_c: control and status register bus_rsp_o.data(sreg_resume_req_c) <= dci.resume_req; bus_rsp_o.data(sreg_execute_req_c) <= dci.execute_req; end case; diff --git a/rtl/core/neorv32_dma.vhd b/rtl/core/neorv32_dma.vhd index 80ff9b71f..22e7b818e 100644 --- a/rtl/core/neorv32_dma.vhd +++ b/rtl/core/neorv32_dma.vhd @@ -57,15 +57,6 @@ end neorv32_dma; architecture neorv32_dma_rtl of neorv32_dma is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(dma_size_c); -- low address boundary bit - - -- control access control -- - signal acc_en : std_ulogic; -- module access enable - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- transfer type register bits -- constant type_num_lo_c : natural := 0; -- r/w: Number of elements to transfer, LSB constant type_num_hi_c : natural := 23; -- r/w: Number of elements to transfer, MSB @@ -140,11 +131,6 @@ begin -- Control Interface ------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = dma_base_c(hi_abb_c downto lo_abb_c)) else '0'; - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -162,7 +148,7 @@ begin config.start <= '0'; elsif rising_edge(clk_i) then config.start <= '0'; -- default - if (wren = '1') then + if (bus_req_i.we = '1') then if (bus_req_i.addr(3 downto 2) = "00") then -- control and status register config.enable <= bus_req_i.data(ctrl_en_c); config.auto <= bus_req_i.data(ctrl_auto_c); @@ -190,9 +176,9 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; -- bus access acknowledge + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- bus access acknowledge bus_rsp_o.data <= (others => '0'); - if (rden = '1') then + if (bus_req_i.re = '1') then case bus_req_i.addr(3 downto 2) is when "00" => -- control and status register bus_rsp_o.data(ctrl_en_c) <= config.enable; diff --git a/rtl/core/neorv32_dmem.entity.vhd b/rtl/core/neorv32_dmem.entity.vhd index 8eb6993af..8e064ed00 100644 --- a/rtl/core/neorv32_dmem.entity.vhd +++ b/rtl/core/neorv32_dmem.entity.vhd @@ -41,7 +41,6 @@ use neorv32.neorv32_package.all; entity neorv32_dmem is generic ( - DMEM_BASE : std_ulogic_vector(31 downto 0); -- memory base address DMEM_SIZE : natural -- processor-internal instruction memory size in bytes ); port ( diff --git a/rtl/core/neorv32_gpio.vhd b/rtl/core/neorv32_gpio.vhd index 6269857cd..4e87cce28 100644 --- a/rtl/core/neorv32_gpio.vhd +++ b/rtl/core/neorv32_gpio.vhd @@ -55,16 +55,6 @@ end neorv32_gpio; architecture neorv32_gpio_rtl of neorv32_gpio is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(gpio_size_c); -- low address boundary bit - - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- accessible regs -- signal din, din_rd, dout, dout_rd : std_ulogic_vector(63 downto 0); @@ -79,23 +69,17 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = gpio_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= gpio_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin if (rstn_i = '0') then dout <= (others => '0'); elsif rising_edge(clk_i) then - if (wren = '1') then - if (addr = gpio_out_lo_addr_c) then + if (bus_req_i.we = '1') then + if (bus_req_i.addr(3 downto 2) = "10") then dout(31 downto 00) <= bus_req_i.data; end if; - if (addr = gpio_out_hi_addr_c) then + if (bus_req_i.addr(3 downto 2) = "11") then dout(63 downto 32) <= bus_req_i.data; end if; end if; @@ -107,11 +91,11 @@ begin begin if rising_edge(clk_i) then -- bus handshake -- - bus_rsp_o.ack <= wren or rden; + bus_rsp_o.ack <= bus_req_i.we or bus_req_i.re; -- read data -- bus_rsp_o.data <= (others => '0'); - if (rden = '1') then - case addr(3 downto 2) is + if (bus_req_i.re = '1') then + case bus_req_i.addr(3 downto 2) is when "00" => bus_rsp_o.data <= din_rd(31 downto 00); when "01" => bus_rsp_o.data <= din_rd(63 downto 32); when "10" => bus_rsp_o.data <= dout_rd(31 downto 00); diff --git a/rtl/core/neorv32_gptmr.vhd b/rtl/core/neorv32_gptmr.vhd index deee5a66b..2e981e4e5 100644 --- a/rtl/core/neorv32_gptmr.vhd +++ b/rtl/core/neorv32_gptmr.vhd @@ -58,10 +58,6 @@ end neorv32_gptmr; architecture neorv32_gptmr_rtl of neorv32_gptmr is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(gptmr_size_c); -- low address boundary bit - -- control register -- constant ctrl_en_c : natural := 0; -- r/w: timer enable constant ctrl_prsc0_c : natural := 1; -- r/w: clock prescaler select bit 0 @@ -71,12 +67,6 @@ architecture neorv32_gptmr_rtl of neorv32_gptmr is -- signal ctrl : std_ulogic_vector(4 downto 0); - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- timer core -- type timer_t is record count : std_ulogic_vector(31 downto 0); -- counter register @@ -92,12 +82,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = gptmr_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= gptmr_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -107,18 +91,18 @@ begin timer.thres <= (others => '0'); elsif rising_edge(clk_i) then timer.cnt_we <= '0'; -- default - if (wren = '1') then - if (addr = gptmr_ctrl_addr_c) then -- control register + if (bus_req_i.we = '1') then + if (bus_req_i.addr(3 downto 2) = "00") then -- control register ctrl(ctrl_en_c) <= bus_req_i.data(ctrl_en_c); ctrl(ctrl_prsc0_c) <= bus_req_i.data(ctrl_prsc0_c); ctrl(ctrl_prsc1_c) <= bus_req_i.data(ctrl_prsc1_c); ctrl(ctrl_prsc2_c) <= bus_req_i.data(ctrl_prsc2_c); ctrl(ctrl_mode_c) <= bus_req_i.data(ctrl_mode_c); end if; - if (addr = gptmr_thres_addr_c) then -- threshold register + if (bus_req_i.addr(3 downto 2) = "01") then -- threshold register timer.thres <= bus_req_i.data; end if; - if (addr = gptmr_count_addr_c) then -- counter register + if (bus_req_i.addr(3 downto 2) = "10") then -- counter register timer.cnt_we <= '1'; end if; end if; @@ -129,10 +113,10 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; -- bus access acknowledge + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- bus access acknowledge bus_rsp_o.data <= (others => '0'); - if (rden = '1') then - case addr(3 downto 2) is + if (bus_req_i.re = '1') then + case bus_req_i.addr(3 downto 2) is when "00" => -- control register bus_rsp_o.data(ctrl_en_c) <= ctrl(ctrl_en_c); bus_rsp_o.data(ctrl_prsc0_c) <= ctrl(ctrl_prsc0_c); diff --git a/rtl/core/neorv32_icache.vhd b/rtl/core/neorv32_icache.vhd index 718b2e136..ed4739c70 100644 --- a/rtl/core/neorv32_icache.vhd +++ b/rtl/core/neorv32_icache.vhd @@ -46,7 +46,8 @@ entity neorv32_icache is generic ( ICACHE_NUM_BLOCKS : natural; -- number of blocks (min 1), has to be a power of 2 ICACHE_BLOCK_SIZE : natural; -- block size in bytes (min 4), has to be a power of 2 - ICACHE_NUM_SETS : natural -- associativity / number of sets (1=direct_mapped), has to be a power of 2 + ICACHE_NUM_SETS : natural; -- associativity / number of sets (1=direct_mapped), has to be a power of 2 + ICACHE_UC_PBEGIN : std_ulogic_vector(3 downto 0) -- begin of uncached address space (page number) ); port ( clk_i : in std_ulogic; -- global clock, rising edge @@ -106,7 +107,7 @@ architecture neorv32_icache_rtl of neorv32_icache is signal cache : cache_if_t; -- control engine -- - type ctrl_engine_state_t is (S_IDLE, S_CLEAR, S_CHECK, S_DOWNLOAD_REQ, S_DOWNLOAD_GET, S_RESYNC); + type ctrl_engine_state_t is (S_IDLE, S_CLEAR, S_CHECK, S_DOWNLOAD_REQ, S_DOWNLOAD_GET, S_DIRECT_REQ, S_DIRECT_GET, S_RESYNC); type ctrl_t is record state : ctrl_engine_state_t; -- current state state_nxt : ctrl_engine_state_t; -- next state @@ -123,7 +124,6 @@ begin -- Sanity Checks -------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- configuration -- assert not (is_power_of_two_f(ICACHE_NUM_BLOCKS) = false) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache number of blocks has to be a power of 2." severity error; assert not (is_power_of_two_f(ICACHE_BLOCK_SIZE) = false) report @@ -136,6 +136,8 @@ begin "NEORV32 PROCESSOR CONFIG ERROR! i-cache block size has to be >= 4." severity error; assert not ((ICACHE_NUM_SETS = 0) or (ICACHE_NUM_SETS > 2)) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache associativity has to be 1 (direct-mapped) or 2 (2-way set-associative)." severity error; + assert false report + "NEORV32 PROCESSOR CONFIG NOTE: i-cache uncached memory space 0x" & to_hstring32_f(ICACHE_UC_PBEGIN & x"0000000") & "..0xffffffff." severity note; -- Control Engine FSM Sync ---------------------------------------------------------------- @@ -194,16 +196,20 @@ begin when S_IDLE => -- wait for host access request or cache control operation -- ------------------------------------------------------------ + ctrl.addr_reg_nxt <= cpu_req_i.addr; if (ctrl.clear_buf = '1') then -- cache control operation? ctrl.state_nxt <= S_CLEAR; - elsif (cpu_req_i.re = '1') or (ctrl.re_buf = '1') then -- cache access - ctrl.state_nxt <= S_CHECK; + elsif (cpu_req_i.re = '1') or (ctrl.re_buf = '1') then + if (unsigned(cpu_req_i.addr(31 downto 28)) >= unsigned(ICACHE_UC_PBEGIN)) then + ctrl.state_nxt <= S_DIRECT_REQ; -- uncached access + else + ctrl.state_nxt <= S_CHECK; -- cache access + end if; end if; when S_CHECK => -- finalize host access if cache hit -- ------------------------------------------------------------ -- calculate block base address - in case we need to download it -- - ctrl.addr_reg_nxt <= cpu_req_i.addr; ctrl.addr_reg_nxt((cache_offset_size_c+2)-1 downto 2) <= (others => '0'); -- block-aligned ctrl.addr_reg_nxt(1 downto 0) <= "00"; -- word-aligned -- @@ -237,6 +243,23 @@ begin end if; end if; + when S_DIRECT_REQ => -- direct access: request new word + -- ------------------------------------------------------------ + bus_req_o.re <= '1'; -- request new read transfer + ctrl.state_nxt <= S_DIRECT_GET; + + when S_DIRECT_GET => -- direct access: wait for bus response + -- ------------------------------------------------------------ + ctrl.re_buf_nxt <= '0'; + cpu_rsp_o.data <= bus_rsp_i.data; + if (bus_rsp_i.err = '1') then + cpu_rsp_o.err <= '1'; + ctrl.state_nxt <= S_IDLE; + elsif (bus_rsp_i.ack = '1') then + cpu_rsp_o.ack <= '1'; + ctrl.state_nxt <= S_IDLE; + end if; + when S_RESYNC => -- re-sync host/cache access: cache read-latency -- ------------------------------------------------------------ ctrl.state_nxt <= S_CHECK; diff --git a/rtl/core/neorv32_imem.entity.vhd b/rtl/core/neorv32_imem.entity.vhd index dc82f32a2..6e9e63e4f 100644 --- a/rtl/core/neorv32_imem.entity.vhd +++ b/rtl/core/neorv32_imem.entity.vhd @@ -41,7 +41,6 @@ use neorv32.neorv32_package.all; entity neorv32_imem is generic ( - IMEM_BASE : std_ulogic_vector(31 downto 0); -- memory base address IMEM_SIZE : natural; -- processor-internal instruction memory size in bytes IMEM_AS_IROM : boolean -- implement IMEM as pre-initialized read-only memory? ); diff --git a/rtl/core/neorv32_intercon.vhd b/rtl/core/neorv32_intercon.vhd new file mode 100644 index 000000000..c0a868f6b --- /dev/null +++ b/rtl/core/neorv32_intercon.vhd @@ -0,0 +1,684 @@ +-- ################################################################################################# +-- # << NEORV32 - Processor Bus: 2-to-1 Bus Switch >> # +-- # ********************************************************************************************* # +-- # Allows to access a single bus ("p_bus") by two controller ports. Controller port A ("ca_bus") # +-- # has priority over controller port B ("cb_bus"). # +-- # ********************************************************************************************* # +-- # BSD 3-Clause License # +-- # # +-- # Copyright (c) 2023, 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 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # +-- ################################################################################################# + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library neorv32; +use neorv32.neorv32_package.all; + +entity neorv32_busswitch is + generic ( + PORT_A_READ_ONLY : boolean; -- set if port A is read-only + PORT_B_READ_ONLY : boolean -- set if port B is read-only + ); + port ( + clk_i : in std_ulogic; -- global clock, rising edge + rstn_i : in std_ulogic; -- global reset, low-active, async + a_req_i : in bus_req_t; -- host port A: request bus + a_rsp_o : out bus_rsp_t; -- host port A: response bus + b_req_i : in bus_req_t; -- host port B: request bus + b_rsp_o : out bus_rsp_t; -- host port B: response bus + x_req_o : out bus_req_t; -- device port request bus + x_rsp_i : in bus_rsp_t -- device port response bus + ); +end neorv32_busswitch; + +architecture neorv32_busswitch_rtl of neorv32_busswitch is + + -- access requests -- + signal a_rd_req_buf, a_wr_req_buf : std_ulogic; + signal b_rd_req_buf, b_wr_req_buf : std_ulogic; + signal a_req_current, a_req_pending : std_ulogic; + signal b_req_current, b_req_pending : std_ulogic; + + -- internal bus lines -- + signal a_bus_ack, b_bus_ack : std_ulogic; + signal a_bus_err, b_bus_err : std_ulogic; + signal x_bus_we, x_bus_re : std_ulogic; + + -- access arbiter -- + type arbiter_state_t is (IDLE, A_BUSY, A_RETIRE, B_BUSY, B_RETIRE); + type arbiter_t is record + state : arbiter_state_t; + state_nxt : arbiter_state_t; + bus_sel : std_ulogic; + re_trig : std_ulogic; + we_trig : std_ulogic; + end record; + signal arbiter : arbiter_t; + +begin + + -- Access Arbiter ------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + arbiter_sync: process(rstn_i, clk_i) + begin + if (rstn_i = '0') then + arbiter.state <= IDLE; + a_rd_req_buf <= '0'; + a_wr_req_buf <= '0'; + b_rd_req_buf <= '0'; + b_wr_req_buf <= '0'; + elsif rising_edge(clk_i) then + arbiter.state <= arbiter.state_nxt; + -- port A requests -- + a_rd_req_buf <= (a_rd_req_buf or a_req_i.re) and (not (a_bus_err or a_bus_ack)); + a_wr_req_buf <= (a_wr_req_buf or a_req_i.we) and (not (a_bus_err or a_bus_ack)) and bool_to_ulogic_f(PORT_A_READ_ONLY = false); + -- port B requests -- + b_rd_req_buf <= (b_rd_req_buf or b_req_i.re) and (not (b_bus_err or b_bus_ack)); + b_wr_req_buf <= (b_wr_req_buf or b_req_i.we) and (not (b_bus_err or b_bus_ack)) and bool_to_ulogic_f(PORT_B_READ_ONLY = false); + end if; + end process arbiter_sync; + + -- any current requests? -- + a_req_current <= (a_req_i.re or a_req_i.we) when (PORT_A_READ_ONLY = false) else a_req_i.re; + b_req_current <= (b_req_i.re or b_req_i.we) when (PORT_B_READ_ONLY = false) else b_req_i.re; + + -- any pending requests? -- + a_req_pending <= (a_rd_req_buf or a_wr_req_buf) when (PORT_A_READ_ONLY = false) else a_rd_req_buf; + b_req_pending <= (b_rd_req_buf or b_wr_req_buf) when (PORT_B_READ_ONLY = false) else b_rd_req_buf; + + -- FSM -- + arbiter_comb: process(arbiter, a_req_current, b_req_current, a_req_pending, b_req_pending, + a_rd_req_buf, a_wr_req_buf, b_rd_req_buf, b_wr_req_buf, x_rsp_i) + begin + -- arbiter defaults -- + arbiter.state_nxt <= arbiter.state; + arbiter.bus_sel <= '0'; + arbiter.we_trig <= '0'; + arbiter.re_trig <= '0'; + + -- state machine -- + case arbiter.state is + + when IDLE => -- wait for requests + -- ------------------------------------------------------------ + if (a_req_current = '1') then -- current request from port A? + arbiter.bus_sel <= '0'; + arbiter.state_nxt <= A_BUSY; + elsif (a_req_pending = '1') then -- pending request from port A? + arbiter.bus_sel <= '0'; + arbiter.state_nxt <= A_RETIRE; + elsif (b_req_current = '1') then -- pending request from port B? + arbiter.bus_sel <= '1'; + arbiter.state_nxt <= B_BUSY; + elsif (b_req_pending = '1') then -- current request from port B? + arbiter.bus_sel <= '1'; + arbiter.state_nxt <= B_RETIRE; + end if; + + when A_BUSY => -- port A pending access + -- ------------------------------------------------------------ + arbiter.bus_sel <= '0'; -- access from port A + if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then +-- [NOTE] Directly return to IDLE state to further promote port A access requests. +-- if (b_req_pending = '1') or (b_req_current = '1') then -- any request from B? +-- arbiter.state_nxt <= B_RETIRE; +-- else + arbiter.state_nxt <= IDLE; +-- end if; + end if; + + when A_RETIRE => -- retire port A pending access + -- ------------------------------------------------------------ + arbiter.bus_sel <= '0'; -- access from port A + arbiter.we_trig <= a_wr_req_buf; + arbiter.re_trig <= a_rd_req_buf; + arbiter.state_nxt <= A_BUSY; + + when B_BUSY => -- port B pending access + -- ------------------------------------------------------------ + arbiter.bus_sel <= '1'; -- access from port B + if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then + if (a_req_pending = '1') or (a_req_current = '1') then -- any request from A? + arbiter.state_nxt <= A_RETIRE; + else + arbiter.state_nxt <= IDLE; + end if; + end if; + + when B_RETIRE => -- retire port B pending access + -- ------------------------------------------------------------ + arbiter.bus_sel <= '1'; -- access from port B + arbiter.we_trig <= b_wr_req_buf; + arbiter.re_trig <= b_rd_req_buf; + arbiter.state_nxt <= B_BUSY; + + when others => -- undefined + -- ------------------------------------------------------------ + arbiter.state_nxt <= IDLE; + + end case; + end process arbiter_comb; + + + -- Peripheral Bus Switch ------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + x_req_o.addr <= a_req_i.addr when (arbiter.bus_sel = '0') else b_req_i.addr; + + x_req_o.data <= b_req_i.data when (PORT_A_READ_ONLY = true) else + a_req_i.data when (PORT_B_READ_ONLY = true) else + a_req_i.data when (arbiter.bus_sel = '0') else b_req_i.data; + + x_req_o.ben <= b_req_i.ben when (PORT_A_READ_ONLY = true) else + a_req_i.ben when (PORT_B_READ_ONLY = true) else + a_req_i.ben when (arbiter.bus_sel = '0') else b_req_i.ben; + + x_req_o.priv <= a_req_i.priv when (arbiter.bus_sel = '0') else b_req_i.priv; + x_req_o.src <= a_req_i.src when (arbiter.bus_sel = '0') else b_req_i.src; + + x_bus_we <= a_req_i.we when (arbiter.bus_sel = '0') else b_req_i.we; + x_bus_re <= a_req_i.re when (arbiter.bus_sel = '0') else b_req_i.re; + x_req_o.we <= x_bus_we or arbiter.we_trig; + x_req_o.re <= x_bus_re or arbiter.re_trig; + + a_rsp_o.data <= x_rsp_i.data; + b_rsp_o.data <= x_rsp_i.data; + + a_bus_ack <= x_rsp_i.ack when (arbiter.bus_sel = '0') else '0'; + b_bus_ack <= x_rsp_i.ack when (arbiter.bus_sel = '1') else '0'; + a_rsp_o.ack <= a_bus_ack; + b_rsp_o.ack <= b_bus_ack; + + a_bus_err <= x_rsp_i.err when (arbiter.bus_sel = '0') else '0'; + b_bus_err <= x_rsp_i.err when (arbiter.bus_sel = '1') else '0'; + a_rsp_o.err <= a_bus_err; + b_rsp_o.err <= b_bus_err; + + +end neorv32_busswitch_rtl; + + +-- ############################################################################################################################ +-- ############################################################################################################################ + + +-- ################################################################################################# +-- # << NEORV32 - Processor Bus: Section Gateway >> # +-- # ********************************************************************************************* # +-- # Bus gateway to distribute the core's access to the processor's main memory sections: # +-- # -> IMEM - internal instruction memory [optional], {rwx} # +-- # -> DMEM - internal data memory [optional], {rwx} # +-- # -> XIP - memory-mapped XIP flash [optional], {r-x} # +-- # -> BOOT - internal bootloader ROM [optional], {r-x} # +-- # -> IO - internal IO devices [mandatory], {rw-} # +-- # All accesses that do not match any of these sections are redirected to the "external" port. # +-- # The gateway-internal bus monitor ensures that all processor-internal accesses are completed # +-- # within a fixed time window. # +-- # This module also enforces the region's PMAs (physical memory attributes). # +-- # ********************************************************************************************* # +-- # BSD 3-Clause License # +-- # # +-- # Copyright (c) 2023, 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 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # +-- ################################################################################################# + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library neorv32; +use neorv32.neorv32_package.all; + +entity neorv32_gateway is + generic ( + TIMEOUT : positive; -- internal bus timeout cycles + -- IMEM port -- + IMEM_ENABLE : boolean; + IMEM_BASE : std_ulogic_vector(31 downto 0); + IMEM_SIZE : positive; + -- DMEM port -- + DMEM_ENABLE : boolean; + DMEM_BASE : std_ulogic_vector(31 downto 0); + DMEM_SIZE : positive; + -- XIP port -- + XIP_ENABLE : boolean; + XIP_BASE : std_ulogic_vector(31 downto 0); + XIP_SIZE : positive; + -- BOOT ROM port -- + BOOT_ENABLE : boolean; + BOOT_BASE : std_ulogic_vector(31 downto 0); + BOOT_SIZE : positive; + -- IO port -- + IO_ENABLE : boolean; + IO_REQ_REG : boolean; + IO_RSP_REG : boolean; + IO_BASE : std_ulogic_vector(31 downto 0); + IO_SIZE : positive; + -- EXTERNAL port -- + EXT_ENABLE : boolean + ); + port ( + -- global control -- + clk_i : in std_ulogic; -- global clock, rising edge + rstn_i : in std_ulogic; -- global reset, low-active, async + -- host port -- + main_req_i : in bus_req_t; -- host request + main_rsp_o : out bus_rsp_t; -- host response + -- section ports -- + imem_req_o : out bus_req_t; + imem_rsp_i : in bus_rsp_t; + dmem_req_o : out bus_req_t; + dmem_rsp_i : in bus_rsp_t; + xip_req_o : out bus_req_t; + xip_rsp_i : in bus_rsp_t; + boot_req_o : out bus_req_t; + boot_rsp_i : in bus_rsp_t; + io_req_o : out bus_req_t; + io_rsp_i : in bus_rsp_t; + ext_req_o : out bus_req_t; + ext_rsp_i : in bus_rsp_t + ); +end neorv32_gateway; + +architecture neorv32_gateway_rtl of neorv32_gateway is + + -- port select -- + constant port_imem_c : natural := 0; + constant port_dmem_c : natural := 1; + constant port_xip_c : natural := 2; + constant port_boot_c : natural := 3; + constant port_io_c : natural := 4; + constant port_ext_c : natural := 5; + signal port_en : std_ulogic_vector(5 downto 0); + + -- IO buffer stage -- + signal io_req : bus_req_t; + signal io_rsp : bus_rsp_t; + + -- response summary -- + signal int_rsp : bus_rsp_t; + + -- bus monitor -- + type keeper_t is record + busy : std_ulogic; + cnt : std_ulogic_vector(index_size_f(TIMEOUT) downto 0); + err : std_ulogic; + halt : std_ulogic; + end record; + signal keeper : keeper_t; + +begin + + -- Sanity Checks -------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + assert false report + "NEORV32 PROCESSOR CONFIG NOTE: Processor-internal bus timeout after " & integer'image(TIMEOUT) & " cycles." severity note; + + + -- Address Section Decoder ---------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + port_en(port_imem_c) <= '1' when (main_req_i.addr(31 downto index_size_f(IMEM_SIZE)) = IMEM_BASE(31 downto index_size_f(IMEM_SIZE))) and (IMEM_ENABLE = true) else '0'; + port_en(port_dmem_c) <= '1' when (main_req_i.addr(31 downto index_size_f(DMEM_SIZE)) = DMEM_BASE(31 downto index_size_f(DMEM_SIZE))) and (DMEM_ENABLE = true) else '0'; + port_en(port_xip_c) <= '1' when (main_req_i.addr(31 downto index_size_f(XIP_SIZE)) = XIP_BASE( 31 downto index_size_f(XIP_SIZE))) and (XIP_ENABLE = true) else '0'; + port_en(port_boot_c) <= '1' when (main_req_i.addr(31 downto index_size_f(BOOT_SIZE)) = BOOT_BASE(31 downto index_size_f(BOOT_SIZE))) and (BOOT_ENABLE = true) else '0'; + port_en(port_io_c) <= '1' when (main_req_i.addr(31 downto index_size_f(IO_SIZE)) = IO_BASE( 31 downto index_size_f(IO_SIZE))) and (IO_ENABLE = true) else '0'; + + -- accesses to the "void" (= no section is matched) are redirected to the external bus interface -- + port_en(port_ext_c) <= '1' when (port_en(port_imem_c) = '0') and + (port_en(port_dmem_c) = '0') and + (port_en(port_xip_c) = '0') and + (port_en(port_boot_c) = '0') and + (port_en(port_io_c) = '0') and (EXT_ENABLE = true) else '0'; + + + -- Bus Request (enforce PMAs) ------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + request: process(main_req_i, port_en) + begin + imem_req_o <= main_req_i; + imem_req_o.we <= main_req_i.we and port_en(port_imem_c); + imem_req_o.re <= main_req_i.re and port_en(port_imem_c); + -- + dmem_req_o <= main_req_i; + dmem_req_o.we <= main_req_i.we and port_en(port_dmem_c); + dmem_req_o.re <= main_req_i.re and port_en(port_dmem_c); + -- + xip_req_o <= main_req_i; + xip_req_o.we <= '0'; -- PMA: read-only + xip_req_o.re <= main_req_i.re and port_en(port_xip_c); + -- + boot_req_o <= main_req_i; + boot_req_o.we <= '0'; -- PMA: read-only + boot_req_o.re <= main_req_i.re and port_en(port_boot_c); + -- + io_req <= main_req_i; + io_req.we <= main_req_i.we and port_en(port_io_c); + io_req.re <= main_req_i.re and port_en(port_io_c); + -- + ext_req_o <= main_req_i; + ext_req_o.we <= main_req_i.we and port_en(port_ext_c); + ext_req_o.re <= main_req_i.re and port_en(port_ext_c); + end process request; + + + -- IO Port Register Stages ---------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + io_req_buffer_true: + if (IO_REQ_REG = true) generate + io_req_buffer: process(rstn_i, clk_i) + begin + if (rstn_i = '0') then + io_req_o <= req_terminate_c; + elsif rising_edge(clk_i) then + io_req_o <= io_req; + end if; + end process io_req_buffer; + end generate; + + io_req_buffer_false: + if (IO_REQ_REG = false) generate + io_req_o <= io_req; + end generate; + + + io_rsp_buffer_true: + if (IO_RSP_REG = true) generate + io_rsp_buffer: process(rstn_i, clk_i) + begin + if (rstn_i = '0') then + io_rsp <= rsp_terminate_c; + elsif rising_edge(clk_i) then + io_rsp <= io_rsp_i; + end if; + end process io_rsp_buffer; + end generate; + + io_rsp_buffer_false: + if (IO_RSP_REG = false) generate + io_rsp <= io_rsp_i; + end generate; + + + -- Bus Response --------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + response: process(imem_rsp_i, dmem_rsp_i, boot_rsp_i, xip_rsp_i, io_rsp, ext_rsp_i) + variable tmp_v : bus_rsp_t; + begin + tmp_v := rsp_terminate_c; -- start will all-zero + if (IMEM_ENABLE = true) then + tmp_v.data := tmp_v.data or imem_rsp_i.data; + tmp_v.ack := tmp_v.ack or imem_rsp_i.ack; + tmp_v.err := tmp_v.err or imem_rsp_i.err; + end if; + if (DMEM_ENABLE = true) then + tmp_v.data := tmp_v.data or dmem_rsp_i.data; + tmp_v.ack := tmp_v.ack or dmem_rsp_i.ack; + tmp_v.err := tmp_v.err or dmem_rsp_i.err; + end if; + if (XIP_ENABLE = true) then + tmp_v.data := tmp_v.data or xip_rsp_i.data; + tmp_v.ack := tmp_v.ack or xip_rsp_i.ack; + tmp_v.err := tmp_v.err or xip_rsp_i.err; + end if; + if (BOOT_ENABLE = true) then + tmp_v.data := tmp_v.data or boot_rsp_i.data; + tmp_v.ack := tmp_v.ack or boot_rsp_i.ack; + tmp_v.err := tmp_v.err or boot_rsp_i.err; + end if; + if (IO_ENABLE = true) then + tmp_v.data := tmp_v.data or io_rsp.data; + tmp_v.ack := tmp_v.ack or io_rsp.ack; + tmp_v.err := tmp_v.err or io_rsp.err; + end if; + if (EXT_ENABLE = true) then + tmp_v.data := tmp_v.data or ext_rsp_i.data; + tmp_v.ack := tmp_v.ack or ext_rsp_i.ack; + tmp_v.err := tmp_v.err or ext_rsp_i.err; + end if; + int_rsp <= tmp_v; + end process response; + + -- host response -- + main_rsp_o.data <= int_rsp.data; + main_rsp_o.ack <= int_rsp.ack; + main_rsp_o.err <= keeper.err; + + + -- Bus Monitor (aka "the KEEPER") --------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + bus_monitor: process(rstn_i, clk_i) + begin + if (rstn_i = '0') then + keeper.busy <= '0'; + keeper.cnt <= (others => '0'); + keeper.err <= '0'; + keeper.halt <= '0'; + elsif rising_edge(clk_i) then + -- defaults -- + keeper.err <= '0'; + keeper.halt <= port_en(port_xip_c) or port_en(port_ext_c); -- no timeout if XIP or EXTERNAL access + -- fsm -- + if (keeper.busy = '0') then -- bus idle + keeper.cnt <= std_ulogic_vector(to_unsigned(TIMEOUT, keeper.cnt'length)); + if (main_req_i.re = '1') or (main_req_i.we = '1') then + keeper.busy <= '1'; + end if; + else -- bus access in progress + keeper.cnt <= std_ulogic_vector(unsigned(keeper.cnt) - 1); + if (int_rsp.err = '1') or ((or_reduce_f(keeper.cnt) = '0') and (keeper.halt = '0')) then -- bus error or timeout + keeper.err <= '1'; + keeper.busy <= '0'; + elsif (int_rsp.ack = '1') then -- normal access termination + keeper.busy <= '0'; + end if; + end if; + end if; + end process bus_monitor; + + +end neorv32_gateway_rtl; + + +-- ############################################################################################################################ +-- ############################################################################################################################ + + +-- ################################################################################################# +-- # << NEORV32 - Processor Bus: IO Switch >> # +-- # ********************************************************************************************* # +-- # Simple address decoding switch for the processor's internal IO/peripheral devices. # +-- # ********************************************************************************************* # +-- # BSD 3-Clause License # +-- # # +-- # Copyright (c) 2023, 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 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # +-- ################################################################################################# + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library neorv32; +use neorv32.neorv32_package.all; + +entity io_switch is + generic ( + DEV_SIZE : natural; -- size of a single IO device, has to be a power of two + -- device base addresses -- + DEV_00_BASE : std_ulogic_vector(31 downto 0); + DEV_01_BASE : std_ulogic_vector(31 downto 0); + DEV_02_BASE : std_ulogic_vector(31 downto 0); + DEV_03_BASE : std_ulogic_vector(31 downto 0); + DEV_04_BASE : std_ulogic_vector(31 downto 0); + DEV_05_BASE : std_ulogic_vector(31 downto 0); + DEV_06_BASE : std_ulogic_vector(31 downto 0); + DEV_07_BASE : std_ulogic_vector(31 downto 0); + DEV_08_BASE : std_ulogic_vector(31 downto 0); + DEV_09_BASE : std_ulogic_vector(31 downto 0); + DEV_10_BASE : std_ulogic_vector(31 downto 0); + DEV_11_BASE : std_ulogic_vector(31 downto 0); + DEV_12_BASE : std_ulogic_vector(31 downto 0); + DEV_13_BASE : std_ulogic_vector(31 downto 0); + DEV_14_BASE : std_ulogic_vector(31 downto 0); + DEV_15_BASE : std_ulogic_vector(31 downto 0); + DEV_16_BASE : std_ulogic_vector(31 downto 0); + DEV_17_BASE : std_ulogic_vector(31 downto 0); + DEV_18_BASE : std_ulogic_vector(31 downto 0); + DEV_19_BASE : std_ulogic_vector(31 downto 0); + DEV_20_BASE : std_ulogic_vector(31 downto 0) + ); + port ( + -- host port -- + main_req_i : in bus_req_t; -- host request + main_rsp_o : out bus_rsp_t; -- host response + -- device ports -- + dev_req_o : out bus_req_array_t; + dev_rsp_i : in bus_rsp_array_t + ); +end io_switch; + +architecture io_switch_rtl of io_switch is + + -- module configuration -- + constant num_devs_physical_c : natural := 21; -- actual number of devices, max num_devs_logical_c + constant num_devs_logical_c : natural := 32; -- logical max number of devices; do not change! + -- + constant lo_c : natural := index_size_f(DEV_SIZE); -- low address boundary bit + constant hi_c : natural := (index_size_f(DEV_SIZE) + index_size_f(num_devs_logical_c)) - 1; -- high address boundary bit + + signal device_sel : std_ulogic_vector(num_devs_physical_c-1 downto 0); -- device select, one-hot + +begin + + -- Device Decoder ------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + device_sel(00) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_00_BASE(hi_c downto lo_c)) else '0'; + device_sel(01) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_01_BASE(hi_c downto lo_c)) else '0'; + device_sel(02) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_02_BASE(hi_c downto lo_c)) else '0'; + device_sel(03) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_03_BASE(hi_c downto lo_c)) else '0'; + device_sel(04) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_04_BASE(hi_c downto lo_c)) else '0'; + device_sel(05) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_05_BASE(hi_c downto lo_c)) else '0'; + device_sel(06) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_06_BASE(hi_c downto lo_c)) else '0'; + device_sel(07) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_07_BASE(hi_c downto lo_c)) else '0'; + device_sel(08) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_08_BASE(hi_c downto lo_c)) else '0'; + device_sel(09) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_09_BASE(hi_c downto lo_c)) else '0'; + device_sel(10) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_10_BASE(hi_c downto lo_c)) else '0'; + device_sel(11) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_11_BASE(hi_c downto lo_c)) else '0'; + device_sel(12) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_12_BASE(hi_c downto lo_c)) else '0'; + device_sel(13) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_13_BASE(hi_c downto lo_c)) else '0'; + device_sel(14) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_14_BASE(hi_c downto lo_c)) else '0'; + device_sel(15) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_15_BASE(hi_c downto lo_c)) else '0'; + device_sel(16) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_16_BASE(hi_c downto lo_c)) else '0'; + device_sel(17) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_17_BASE(hi_c downto lo_c)) else '0'; + device_sel(18) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_18_BASE(hi_c downto lo_c)) else '0'; + device_sel(19) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_19_BASE(hi_c downto lo_c)) else '0'; + device_sel(20) <= '1' when (main_req_i.addr(hi_c downto lo_c) = DEV_20_BASE(hi_c downto lo_c)) else '0'; + + + -- Device Requests ------------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + request_gen: + for i in 0 to (num_devs_physical_c-1) generate + dev_req_o(i).addr <= main_req_i.addr; + dev_req_o(i).data <= main_req_i.data; + dev_req_o(i).ben <= main_req_i.ben; + dev_req_o(i).we <= main_req_i.we and device_sel(i); + dev_req_o(i).re <= main_req_i.re and device_sel(i); + dev_req_o(i).src <= main_req_i.src; + dev_req_o(i).priv <= main_req_i.priv; + end generate; + + + -- Global Response ------------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + bus_response: process(dev_rsp_i) + variable tmp_v : bus_rsp_t; + begin + tmp_v := rsp_terminate_c; -- start with all-zero + for i in 0 to (num_devs_physical_c-1) loop -- OR all response signals + tmp_v.data := tmp_v.data or dev_rsp_i(i).data; + tmp_v.ack := tmp_v.ack or dev_rsp_i(i).ack; + tmp_v.err := tmp_v.err or dev_rsp_i(i).err; + end loop; + main_rsp_o <= tmp_v; + end process; + + +end io_switch_rtl; diff --git a/rtl/core/neorv32_mtime.vhd b/rtl/core/neorv32_mtime.vhd index 76084caf1..758318e6f 100644 --- a/rtl/core/neorv32_mtime.vhd +++ b/rtl/core/neorv32_mtime.vhd @@ -54,16 +54,6 @@ end neorv32_mtime; architecture neorv32_mtime_rtl of neorv32_mtime is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(mtime_size_c); -- low address boundary bit - - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- module access enable - signal rden : std_ulogic; -- read enable - -- time write access buffer -- signal mtime_lo_we : std_ulogic; signal mtime_hi_we : std_ulogic; @@ -84,14 +74,6 @@ architecture neorv32_mtime_rtl of neorv32_mtime is begin - -- Access Control ------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = mtime_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= mtime_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - - -- Write Access --------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- write_access: process(rstn_i, clk_i) @@ -106,23 +88,23 @@ begin mtime_hi <= (others => '0'); elsif rising_edge(clk_i) then -- mtimecmp -- - if (wren = '1') then - if (addr = mtime_cmp_lo_addr_c) then + if (bus_req_i.we = '1') then + if (bus_req_i.addr(3 downto 2) = "10") then mtimecmp_lo <= bus_req_i.data; end if; - if (addr = mtime_cmp_hi_addr_c) then + if (bus_req_i.addr(3 downto 2) = "11") then mtimecmp_hi <= bus_req_i.data; end if; end if; -- mtime write access buffer -- mtime_lo_we <= '0'; - if (wren = '1') and (addr = mtime_time_lo_addr_c) then + if (bus_req_i.we = '1') and (bus_req_i.addr(3 downto 2) = "00") then mtime_lo_we <= '1'; end if; -- mtime_hi_we <= '0'; - if (wren = '1') and (addr = mtime_time_hi_addr_c) then + if (bus_req_i.we = '1') and (bus_req_i.addr(3 downto 2) = "01") then mtime_hi_we <= '1'; end if; @@ -152,10 +134,10 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; -- bus handshake + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- bus handshake bus_rsp_o.data <= (others => '0'); -- default - if (rden = '1') then - case addr(3 downto 2) is + if (bus_req_i.re = '1') then + case bus_req_i.addr(3 downto 2) is when "00" => bus_rsp_o.data <= mtime_lo; when "01" => bus_rsp_o.data <= mtime_hi; when "10" => bus_rsp_o.data <= mtimecmp_lo; diff --git a/rtl/core/neorv32_neoled.vhd b/rtl/core/neorv32_neoled.vhd index 9ccb96054..037c037eb 100644 --- a/rtl/core/neorv32_neoled.vhd +++ b/rtl/core/neorv32_neoled.vhd @@ -71,16 +71,6 @@ end neorv32_neoled; architecture neorv32_neoled_rtl of neorv32_neoled is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(neoled_size_c); -- low address boundary bit - - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- Control register bits -- constant ctrl_en_c : natural := 0; -- r/w: module enable constant ctrl_mode_c : natural := 1; -- r/w: 0 = 24-bit RGB mode, 1 = 32-bit RGBW mode @@ -175,12 +165,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = neoled_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= neoled_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -194,7 +178,7 @@ begin ctrl.t0_high <= (others => '0'); ctrl.t1_high <= (others => '0'); elsif rising_edge(clk_i) then - if (wren = '1') and (addr = neoled_ctrl_addr_c) then + if (bus_req_i.we = '1') and (bus_req_i.addr(2) = '0') then ctrl.enable <= bus_req_i.data(ctrl_en_c); ctrl.mode <= bus_req_i.data(ctrl_mode_c); ctrl.strobe <= bus_req_i.data(ctrl_strobe_c); @@ -211,9 +195,9 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= wren or rden; -- access acknowledge + bus_rsp_o.ack <= bus_req_i.we or bus_req_i.re; -- access acknowledge bus_rsp_o.data <= (others => '0'); - if (rden = '1') then -- and (addr = neoled_ctrl_addr_c) then + if (bus_req_i.re = '1') then bus_rsp_o.data(ctrl_en_c) <= ctrl.enable; bus_rsp_o.data(ctrl_mode_c) <= ctrl.mode; bus_rsp_o.data(ctrl_strobe_c) <= ctrl.strobe; @@ -265,7 +249,7 @@ begin ); tx_fifo.re <= '1' when (serial.state = "100") else '0'; - tx_fifo.we <= '1' when (wren = '1') and (addr = neoled_data_addr_c) else '0'; + tx_fifo.we <= '1' when (bus_req_i.we = '1') and (bus_req_i.addr(2) = '1') else '0'; tx_fifo.wdata <= ctrl.strobe & ctrl.mode & bus_req_i.data; tx_fifo.clear <= not ctrl.enable; diff --git a/rtl/core/neorv32_onewire.vhd b/rtl/core/neorv32_onewire.vhd index 1a9ec37db..88c0fc175 100644 --- a/rtl/core/neorv32_onewire.vhd +++ b/rtl/core/neorv32_onewire.vhd @@ -74,10 +74,6 @@ architecture neorv32_onewire_rtl of neorv32_onewire is constant t_presence_end_c : unsigned(6 downto 0) := to_unsigned(96, 7); -- t6 -- -> see data sheet for more information about the t* timing values -- - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(twi_size_c); -- low address boundary bit - -- control register -- constant ctrl_en_c : natural := 0; -- r/w: TWI enable constant ctrl_prsc0_c : natural := 1; -- r/w: prescaler select bit 0 @@ -98,12 +94,6 @@ architecture neorv32_onewire_rtl of neorv32_onewire is constant ctrl_presence_c : natural := 30; -- r/-: bus presence detected constant ctrl_busy_c : natural := 31; -- r/-: set while operation in progress - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- control register -- type ctrl_t is record enable : std_ulogic; @@ -146,12 +136,6 @@ begin -- Write Access --------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = onewire_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= onewire_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -165,21 +149,21 @@ begin tx_data <= (others => '0'); elsif rising_edge(clk_i) then -- write access -- - if (wren = '1') then + if (bus_req_i.we = '1') then -- control register -- - if (addr = onewire_ctrl_addr_c) then + if (bus_req_i.addr(2) = '0') then ctrl.enable <= bus_req_i.data(ctrl_en_c); ctrl.clk_prsc <= bus_req_i.data(ctrl_prsc1_c downto ctrl_prsc0_c); ctrl.clk_div <= bus_req_i.data(ctrl_clkdiv7_c downto ctrl_clkdiv0_c); end if; -- data register -- - if (addr = onewire_data_addr_c) then + if (bus_req_i.addr(2) = '1') then tx_data <= bus_req_i.data(7 downto 0); end if; end if; -- operation triggers -- - if (wren = '1') and (addr = onewire_ctrl_addr_c) then -- set by host + if (bus_req_i.we = '1') and (bus_req_i.addr(2) = '0') then -- set by host ctrl.trig_rst <= bus_req_i.data(ctrl_trig_rst_c); ctrl.trig_bit <= bus_req_i.data(ctrl_trig_bit_c); ctrl.trig_byte <= bus_req_i.data(ctrl_trig_byte_c); @@ -195,11 +179,11 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; -- bus handshake + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- bus handshake bus_rsp_o.data <= (others => '0'); - if (rden = '1') then + if (bus_req_i.re = '1') then -- control register -- - if (addr = onewire_ctrl_addr_c) then + if (bus_req_i.addr(2) = '0') then bus_rsp_o.data(ctrl_en_c) <= ctrl.enable; bus_rsp_o.data(ctrl_prsc1_c downto ctrl_prsc0_c) <= ctrl.clk_prsc; bus_rsp_o.data(ctrl_clkdiv7_c downto ctrl_clkdiv0_c) <= ctrl.clk_div; @@ -208,7 +192,7 @@ begin bus_rsp_o.data(ctrl_presence_c) <= serial.presence; bus_rsp_o.data(ctrl_busy_c) <= serial.busy; -- data register -- - else -- if (addr = onewire_data_addr_c) then + else bus_rsp_o.data(7 downto 0) <= serial.sreg; end if; end if; diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index 78ca4b047..a7d5ccfbf 100644 --- a/rtl/core/neorv32_package.vhd +++ b/rtl/core/neorv32_package.vhd @@ -44,23 +44,19 @@ package neorv32_package is -- Architecture Configuration ------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- address space -- - constant ispace_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- default instruction memory address space base address - constant dspace_base_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- default data memory address space base address - -- if register x0 is implemented as a *physical register* it has to be explicitly set to zero by the CPU hardware -- constant reset_x0_c : boolean := true; -- has to be 'true' for the default register file rtl description (BRAM-based) -- "response time window" for processor-internal modules -- -- = cycles after which an *unacknowledged* internal bus access will timeout and trigger a bus fault exception - constant max_proc_int_response_time_c : natural := 15; -- default = 15 (min 2) + constant max_proc_int_response_time_c : natural := 15; -- default = 15 -- log2 of co-processor timeout cycles -- constant cp_timeout_c : natural := 7; -- default = 7 (= 128 cycles) -- Architecture Constants ----------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080602"; -- hardware version + constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080605"; -- hardware version constant archid_c : natural := 19; -- official RISC-V architecture ID constant XLEN : natural := 32; -- native data path width, do not change! @@ -82,227 +78,57 @@ package neorv32_package is -- Processor Address Space Layout -- **************************************************************************************************************************** - -- Internal Instruction Memory (IMEM) and Date Memory (DMEM) -- - --> internal data/instruction memory sizes are configured via top's generics - constant imem_base_c : std_ulogic_vector(31 downto 0) := ispace_base_c; -- internal instruction memory base address - constant dmem_base_c : std_ulogic_vector(31 downto 0) := dspace_base_c; -- internal data memory base address - - -- !!! IMPORTANT: The base address of each component/module has to be aligned to the !!! - -- !!! total size of the module's occupied address space. The occupied address space !!! - -- !!! has to be a power of two (minimum 4 bytes). Address spaces must not overlap. !!! - - -- Internal Bootloader ROM -- - -- Actual bootloader size is determined during runtime via the length of the bootloader initialization image - constant boot_rom_base_c : std_ulogic_vector(31 downto 0) := x"ffff0000"; -- bootloader base address, fixed! - constant boot_rom_max_size_c : natural := 32*1024; -- max module's address space size in bytes, fixed! - - -- On-Chip Debugger: Debug Module -- - constant dm_base_c : std_ulogic_vector(31 downto 0) := x"fffff800"; -- base address, fixed! - constant dm_size_c : natural := 4*16*4; -- debug ROM address space size in bytes, fixed - constant dm_code_base_c : std_ulogic_vector(31 downto 0) := x"fffff800"; - constant dm_pbuf_base_c : std_ulogic_vector(31 downto 0) := x"fffff840"; - constant dm_data_base_c : std_ulogic_vector(31 downto 0) := x"fffff880"; - constant dm_sreg_base_c : std_ulogic_vector(31 downto 0) := x"fffff8c0"; - -- park loop entry points - these need to be sync with the OCD firmware (sw/ocd-firmware/park_loop.S) -- - constant dm_exc_entry_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(dm_code_base_c) + 0); -- entry point for exceptions - constant dm_park_entry_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(dm_code_base_c) + 8); -- normal entry point - - -- IO: Internal Peripheral Devices ("IO") Area -- - -- Control register(s) (including the device-enable flag) should be located at the base address of each device - constant io_base_c : std_ulogic_vector(31 downto 0) := x"fffffe00"; - constant io_size_c : natural := 512; -- IO address space size in bytes, fixed! - - -- Custom Functions Subsystem (CFS) -- - constant cfs_base_c : std_ulogic_vector(31 downto 0) := x"fffffe00"; -- base address - constant cfs_size_c : natural := 64*4; -- module's address space in bytes - constant cfs_reg0_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe00"; - constant cfs_reg1_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe04"; - constant cfs_reg2_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe08"; - constant cfs_reg3_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe0c"; - constant cfs_reg4_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe10"; - constant cfs_reg5_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe14"; - constant cfs_reg6_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe18"; - constant cfs_reg7_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe1c"; - constant cfs_reg8_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe20"; - constant cfs_reg9_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe24"; - constant cfs_reg10_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe28"; - constant cfs_reg11_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe2c"; - constant cfs_reg12_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe30"; - constant cfs_reg13_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe34"; - constant cfs_reg14_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe38"; - constant cfs_reg15_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe3c"; - constant cfs_reg16_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe40"; - constant cfs_reg17_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe44"; - constant cfs_reg18_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe48"; - constant cfs_reg19_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe4c"; - constant cfs_reg20_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe50"; - constant cfs_reg21_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe54"; - constant cfs_reg22_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe58"; - constant cfs_reg23_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe5c"; - constant cfs_reg24_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe60"; - constant cfs_reg25_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe64"; - constant cfs_reg26_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe68"; - constant cfs_reg27_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe6c"; - constant cfs_reg28_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe70"; - constant cfs_reg29_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe74"; - constant cfs_reg30_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe78"; - constant cfs_reg31_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe7c"; - constant cfs_reg32_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe80"; - constant cfs_reg33_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe84"; - constant cfs_reg34_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe88"; - constant cfs_reg35_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe8c"; - constant cfs_reg36_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe90"; - constant cfs_reg37_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe94"; - constant cfs_reg38_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe98"; - constant cfs_reg39_addr_c : std_ulogic_vector(31 downto 0) := x"fffffe9c"; - constant cfs_reg40_addr_c : std_ulogic_vector(31 downto 0) := x"fffffea0"; - constant cfs_reg41_addr_c : std_ulogic_vector(31 downto 0) := x"fffffea4"; - constant cfs_reg42_addr_c : std_ulogic_vector(31 downto 0) := x"fffffea8"; - constant cfs_reg43_addr_c : std_ulogic_vector(31 downto 0) := x"fffffeac"; - constant cfs_reg44_addr_c : std_ulogic_vector(31 downto 0) := x"fffffeb0"; - constant cfs_reg45_addr_c : std_ulogic_vector(31 downto 0) := x"fffffeb4"; - constant cfs_reg46_addr_c : std_ulogic_vector(31 downto 0) := x"fffffeb8"; - constant cfs_reg47_addr_c : std_ulogic_vector(31 downto 0) := x"fffffebc"; - constant cfs_reg48_addr_c : std_ulogic_vector(31 downto 0) := x"fffffec0"; - constant cfs_reg49_addr_c : std_ulogic_vector(31 downto 0) := x"fffffec4"; - constant cfs_reg50_addr_c : std_ulogic_vector(31 downto 0) := x"fffffec8"; - constant cfs_reg51_addr_c : std_ulogic_vector(31 downto 0) := x"fffffecc"; - constant cfs_reg52_addr_c : std_ulogic_vector(31 downto 0) := x"fffffed0"; - constant cfs_reg53_addr_c : std_ulogic_vector(31 downto 0) := x"fffffed4"; - constant cfs_reg54_addr_c : std_ulogic_vector(31 downto 0) := x"fffffed8"; - constant cfs_reg55_addr_c : std_ulogic_vector(31 downto 0) := x"fffffedc"; - constant cfs_reg56_addr_c : std_ulogic_vector(31 downto 0) := x"fffffee0"; - constant cfs_reg57_addr_c : std_ulogic_vector(31 downto 0) := x"fffffee4"; - constant cfs_reg58_addr_c : std_ulogic_vector(31 downto 0) := x"fffffee8"; - constant cfs_reg59_addr_c : std_ulogic_vector(31 downto 0) := x"fffffeec"; - constant cfs_reg60_addr_c : std_ulogic_vector(31 downto 0) := x"fffffef0"; - constant cfs_reg61_addr_c : std_ulogic_vector(31 downto 0) := x"fffffef4"; - constant cfs_reg62_addr_c : std_ulogic_vector(31 downto 0) := x"fffffef8"; - constant cfs_reg63_addr_c : std_ulogic_vector(31 downto 0) := x"fffffefc"; - - -- Serial Data Interface (SDI) -- - constant sdi_base_c : std_ulogic_vector(31 downto 0) := x"ffffff00"; -- base address - constant sdi_size_c : natural := 2*4; -- module's address space size in bytes - constant sdi_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff00"; - constant sdi_rtx_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff04"; - - -- Stream Link Interface (SLINK) -- - constant slink_base_c : std_ulogic_vector(31 downto 0) := x"ffffff08"; -- base address - constant slink_size_c : natural := 2*4; -- module's address space size in bytes - - -- Direct Memory Access Controller (DMA) -- - constant dma_base_c : std_ulogic_vector(31 downto 0) := x"ffffff10"; -- base address - constant dma_size_c : natural := 4*4; -- module's address space size in bytes - - -- Cyclic Redundancy Check Unit (CRC) -- - constant crc_base_c : std_ulogic_vector(31 downto 0) := x"ffffff20"; -- base address - constant crc_size_c : natural := 4*4; -- module's address space size in bytes - - -- reserved -- ---constant reserved_base_c : std_ulogic_vector(31 downto 0) := x"ffffff30"; -- base address ---constant reserved_size_c : natural := 4*4; -- module's address space size in bytes - - -- Execute In-Place Module (XIP) -- - constant xip_base_c : std_ulogic_vector(31 downto 0) := x"ffffff40"; -- base address - constant xip_size_c : natural := 4*4; -- module's address space size in bytes - constant xip_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff40"; ---constant xip_reserved_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff44"; - constant xip_data_lo_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff48"; - constant xip_data_hi_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff4C"; - - -- Pulse-Width Modulation Controller (PWM) -- - constant pwm_base_c : std_ulogic_vector(31 downto 0) := x"ffffff50"; -- base address - constant pwm_size_c : natural := 4*4; -- module's address space size in bytes - constant pwm_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff50"; - constant pwm_dc0_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff54"; - constant pwm_dc1_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff58"; - constant pwm_dc2_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff5c"; - - -- General Purpose Timer (GPTMR) -- - constant gptmr_base_c : std_ulogic_vector(31 downto 0) := x"ffffff60"; -- base address - constant gptmr_size_c : natural := 4*4; -- module's address space size in bytes - constant gptmr_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff60"; - constant gptmr_thres_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff64"; - constant gptmr_count_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff68"; ---constant gptmr_reserve_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff6c"; - - -- 1-Wire Interface Controller (ONEWIRE) -- - constant onewire_base_c : std_ulogic_vector(31 downto 0) := x"ffffff70"; -- base address - constant onewire_size_c : natural := 2*4; -- module's address space size in bytes - constant onewire_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff70"; - constant onewire_data_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff74"; - ----- reserved -- ---constant reserved_base_c : std_ulogic_vector(31 downto 0) := x"ffffff78"; -- base address ---constant reserved_size_c : natural := 2*4; -- module's address space size in bytes - - -- External Interrupt Controller (XIRQ) -- - constant xirq_base_c : std_ulogic_vector(31 downto 0) := x"ffffff80"; -- base address - constant xirq_size_c : natural := 4*4; -- module's address space size in bytes - constant xirq_enable_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff80"; - constant xirq_pending_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff84"; - constant xirq_source_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff88"; ---constant xirq_reserved_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff8c"; - - -- Machine System Timer (MTIME) -- - constant mtime_base_c : std_ulogic_vector(31 downto 0) := x"ffffff90"; -- base address - constant mtime_size_c : natural := 4*4; -- module's address space size in bytes - constant mtime_time_lo_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff90"; - constant mtime_time_hi_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff94"; - constant mtime_cmp_lo_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff98"; - constant mtime_cmp_hi_addr_c : std_ulogic_vector(31 downto 0) := x"ffffff9c"; - - -- Primary Universal Asynchronous Receiver/Transmitter (UART0) -- - constant uart0_base_c : std_ulogic_vector(31 downto 0) := x"ffffffa0"; -- base address - constant uart0_size_c : natural := 2*4; -- module's address space size in bytes - constant uart0_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffa0"; - constant uart0_rtx_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffa4"; - - -- Serial Peripheral Interface (SPI) -- - constant spi_base_c : std_ulogic_vector(31 downto 0) := x"ffffffa8"; -- base address - constant spi_size_c : natural := 2*4; -- module's address space size in bytes - constant spi_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffa8"; - constant spi_rtx_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffac"; - - -- Two Wire Interface (TWI) -- - constant twi_base_c : std_ulogic_vector(31 downto 0) := x"ffffffb0"; -- base address - constant twi_size_c : natural := 2*4; -- module's address space size in bytes - constant twi_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffb0"; - constant twi_rtx_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffb4"; - - -- True Random Number Generator (TRNG) -- - constant trng_base_c : std_ulogic_vector(31 downto 0) := x"ffffffb8"; -- base address - constant trng_size_c : natural := 1*4; -- module's address space size in bytes - constant trng_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffb8"; - - -- Watch Dog Timer (WDT) -- - constant wdt_base_c : std_ulogic_vector(31 downto 0) := x"ffffffbc"; -- base address - constant wdt_size_c : natural := 1*4; -- module's address space size in bytes - constant wdt_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffbc"; - - -- General Purpose Input/Output Controller (GPIO) -- - constant gpio_base_c : std_ulogic_vector(31 downto 0) := x"ffffffc0"; -- base address - constant gpio_size_c : natural := 4*4; -- module's address space size in bytes - constant gpio_in_lo_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffc0"; - constant gpio_in_hi_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffc4"; - constant gpio_out_lo_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffc8"; - constant gpio_out_hi_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffcc"; - - -- Secondary Universal Asynchronous Receiver/Transmitter (UART1) -- - constant uart1_base_c : std_ulogic_vector(31 downto 0) := x"ffffffd0"; -- base address - constant uart1_size_c : natural := 2*4; -- module's address space size in bytes - constant uart1_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffd0"; - constant uart1_rtx_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffd4"; - - -- Smart LED (WS2811/WS2812) Interface (NEOLED) -- - constant neoled_base_c : std_ulogic_vector(31 downto 0) := x"ffffffd8"; -- base address - constant neoled_size_c : natural := 2*4; -- module's address space size in bytes - constant neoled_ctrl_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffd8"; - constant neoled_data_addr_c : std_ulogic_vector(31 downto 0) := x"ffffffdc"; - - -- System Information Memory (SYSINFO) -- - constant sysinfo_base_c : std_ulogic_vector(31 downto 0) := x"ffffffe0"; -- base address - constant sysinfo_size_c : natural := 8*4; -- module's address space size in bytes + -- Main Address Regions --- + constant mem_ispace_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- IMEM size via generic + constant mem_dspace_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 (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_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe000"; -- reserved +--constant base_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe100"; -- reserved +--constant base_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe200"; -- reserved +--constant base_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe300"; -- reserved +--constant base_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe400"; -- reserved +--constant base_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe500"; -- reserved +--constant base_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe600"; -- reserved +--constant base_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe700"; -- reserved +--constant base_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe800"; -- reserved +--constant base_res_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffe900"; -- reserved +--constant base_res_cfs_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"; + + -- OCD Debug Module Entry Points -- + 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 @@ -361,6 +187,10 @@ package neorv32_package is err => '0' ); + -- pre-constrained array types -- + type bus_req_array_t is array (20 downto 0) of bus_req_t; + type bus_rsp_array_t is array (20 downto 0) of bus_rsp_t; + -- **************************************************************************************************************************** -- RISC-V ISA Definitions diff --git a/rtl/core/neorv32_pwm.vhd b/rtl/core/neorv32_pwm.vhd index 7719091fe..947fd04bb 100644 --- a/rtl/core/neorv32_pwm.vhd +++ b/rtl/core/neorv32_pwm.vhd @@ -59,22 +59,12 @@ end neorv32_pwm; architecture neorv32_pwm_rtl of neorv32_pwm is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(pwm_size_c); -- low address boundary bit - -- Control register bits -- constant ctrl_enable_c : natural := 0; -- r/w: PWM enable constant ctrl_prsc0_bit_c : natural := 1; -- r/w: prescaler select bit 0 constant ctrl_prsc1_bit_c : natural := 2; -- r/w: prescaler select bit 1 constant ctrl_prsc2_bit_c : natural := 3; -- r/w: prescaler select bit 2 - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- write enable - signal rden : std_ulogic; -- read enable - -- accessible regs -- type pwm_ch_t is array (0 to 11) of std_ulogic_vector(7 downto 0); signal pwm_ch : pwm_ch_t; -- duty cycle (r/w) @@ -100,12 +90,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = pwm_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= pwm_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - rden <= acc_en and bus_req_i.re; - wren <= acc_en and bus_req_i.we; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -114,28 +98,28 @@ begin prsc <= (others => '0'); pwm_ch <= (others => (others => '0')); elsif rising_edge(clk_i) then - if (wren = '1') then + if (bus_req_i.we = '1') then -- control register -- - if (addr = pwm_ctrl_addr_c) then + if (bus_req_i.addr(3 downto 2) = "00") then enable <= bus_req_i.data(ctrl_enable_c); prsc <= bus_req_i.data(ctrl_prsc2_bit_c downto ctrl_prsc0_bit_c); end if; -- duty cycle register 0 -- - if (addr = pwm_dc0_addr_c) then + if (bus_req_i.addr(3 downto 2) = "01") then pwm_ch(00) <= bus_req_i.data(07 downto 00); pwm_ch(01) <= bus_req_i.data(15 downto 08); pwm_ch(02) <= bus_req_i.data(23 downto 16); pwm_ch(03) <= bus_req_i.data(31 downto 24); end if; -- duty cycle register 1 -- - if (addr = pwm_dc1_addr_c) then + if (bus_req_i.addr(3 downto 2) = "10") then pwm_ch(04) <= bus_req_i.data(07 downto 00); pwm_ch(05) <= bus_req_i.data(15 downto 08); pwm_ch(06) <= bus_req_i.data(23 downto 16); pwm_ch(07) <= bus_req_i.data(31 downto 24); end if; -- duty cycle register 2 -- - if (addr = pwm_dc2_addr_c) then + if (bus_req_i.addr(3 downto 2) = "11") then pwm_ch(08) <= bus_req_i.data(07 downto 00); pwm_ch(09) <= bus_req_i.data(15 downto 08); pwm_ch(10) <= bus_req_i.data(23 downto 16); @@ -149,10 +133,10 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; -- bus handshake + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- bus handshake bus_rsp_o.data <= (others => '0'); - if (rden = '1') then - case addr(3 downto 2) is + if (bus_req_i.re = '1') then + case bus_req_i.addr(3 downto 2) is when "00" => bus_rsp_o.data(ctrl_enable_c) <= enable; bus_rsp_o.data(ctrl_prsc2_bit_c downto ctrl_prsc0_bit_c) <= prsc; when "01" => bus_rsp_o.data <= pwm_ch_rd(03) & pwm_ch_rd(02) & pwm_ch_rd(01) & pwm_ch_rd(00); when "10" => bus_rsp_o.data <= pwm_ch_rd(07) & pwm_ch_rd(06) & pwm_ch_rd(05) & pwm_ch_rd(04); diff --git a/rtl/core/neorv32_sdi.vhd b/rtl/core/neorv32_sdi.vhd index b3a624076..61cce1fe5 100644 --- a/rtl/core/neorv32_sdi.vhd +++ b/rtl/core/neorv32_sdi.vhd @@ -61,10 +61,6 @@ end neorv32_sdi; architecture neorv32_sdi_rtl of neorv32_sdi is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(sdi_size_c); -- low address boundary bit - -- control register -- constant ctrl_en_c : natural := 0; -- r/w: SDI enable constant ctrl_clr_rx_c : natural := 1; -- -/w: clear RX FIFO, auto-clears @@ -86,12 +82,6 @@ architecture neorv32_sdi_rtl of neorv32_sdi is constant ctrl_tx_empty_c : natural := 26; -- r/-: TX FIFO empty constant ctrl_tx_full_c : natural := 27; -- r/-: TX FIFO full - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- control register (see bit definitions above) -- type ctrl_t is record enable : std_ulogic; @@ -151,12 +141,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = sdi_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= sdi_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -169,8 +153,8 @@ begin ctrl.irq_tx_empty <= '0'; elsif rising_edge(clk_i) then ctrl.clr_rx <= '0'; - if (wren = '1') then - if (addr = sdi_ctrl_addr_c) then -- control register + if (bus_req_i.we = '1') then + if (bus_req_i.addr(2) = '0') then -- control register ctrl.enable <= bus_req_i.data(ctrl_en_c); ctrl.clr_rx <= bus_req_i.data(ctrl_clr_rx_c); -- @@ -187,10 +171,10 @@ begin read_aceess: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; -- bus access acknowledge + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- bus access acknowledge bus_rsp_o.data <= (others => '0'); - if (rden = '1') then - if (addr = sdi_ctrl_addr_c) then -- control register + if (bus_req_i.re = '1') then + if (bus_req_i.addr(2) = '0') then -- control register bus_rsp_o.data(ctrl_en_c) <= ctrl.enable; -- bus_rsp_o.data(ctrl_fifo_size3_c downto ctrl_fifo_size0_c) <= std_ulogic_vector(to_unsigned(index_size_f(RTX_FIFO), 4)); @@ -246,7 +230,7 @@ begin -- write access (CPU) -- tx_fifo.clear <= not ctrl.enable; tx_fifo.wdata <= bus_req_i.data(7 downto 0); - tx_fifo.we <= '1' when (wren = '1') and (addr = sdi_rtx_addr_c) else '0'; + tx_fifo.we <= '1' when (bus_req_i.we = '1') and (bus_req_i.addr(2) = '1') else '0'; -- read access (SDI) -- tx_fifo.re <= serial.start; @@ -281,7 +265,7 @@ begin -- read access (CPU) -- rx_fifo.clear <= (not ctrl.enable) or ctrl.clr_rx; - rx_fifo.re <= '1' when (rden = '1') and (addr = sdi_rtx_addr_c) else '0'; + rx_fifo.re <= '1' when (bus_req_i.re = '1') and (bus_req_i.addr(2) = '1') else '0'; -- Input Synchronizer --------------------------------------------------------------------- diff --git a/rtl/core/neorv32_slink.vhd b/rtl/core/neorv32_slink.vhd index 2207b66ac..9f181c7a5 100644 --- a/rtl/core/neorv32_slink.vhd +++ b/rtl/core/neorv32_slink.vhd @@ -67,10 +67,6 @@ end neorv32_slink; architecture neorv32_slink_rtl of neorv32_slink is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(slink_size_c); -- low address boundary bit - -- control register -- constant ctrl_en_c : natural := 0; -- r/w: Global module enable constant ctrl_rx_clr_c : natural := 1; -- -/w: Clear RX FIFO, auto-clears @@ -99,11 +95,6 @@ architecture neorv32_slink_rtl of neorv32_slink is constant ctrl_tx_fifo_size2_c : natural := 30; -- r/-: log2(TX fifo size), bit 2 constant ctrl_tx_fifo_size3_c : natural := 31; -- r/-: log2(TX fifo size), bit 3 (msb) - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- control register (see bit definitions above) -- type ctrl_t is record enable : std_ulogic; @@ -144,11 +135,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = slink_base_c(hi_abb_c downto lo_abb_c)) else '0'; - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -165,7 +151,7 @@ begin elsif rising_edge(clk_i) then ctrl.rx_clr <= '0'; -- auto-clear ctrl.tx_clr <= '0'; -- auto-clear - if (wren = '1') then + if (bus_req_i.we = '1') then if (bus_req_i.addr(2) = '0') then -- control register ctrl.enable <= bus_req_i.data(ctrl_en_c); ctrl.rx_clr <= bus_req_i.data(ctrl_rx_clr_c); @@ -186,9 +172,9 @@ begin read_aceess: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; -- bus access acknowledge + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- bus access acknowledge bus_rsp_o.data <= (others => '0'); - if (rden = '1') then + if (bus_req_i.re = '1') then if (bus_req_i.addr(2) = '0') then -- control register bus_rsp_o.data(ctrl_en_c) <= ctrl.enable; -- @@ -245,7 +231,7 @@ begin ); rx_fifo.clear <= (not ctrl.enable) or ctrl.rx_clr; - rx_fifo.re <= '1' when (rden = '1') and (bus_req_i.addr(2) = '1') else '0'; + rx_fifo.re <= '1' when (bus_req_i.re = '1') and (bus_req_i.addr(2) = '1') else '0'; rx_fifo.we <= slink_rx_valid_i; rx_fifo.wdata <= slink_rx_data_i; @@ -278,7 +264,7 @@ begin ); tx_fifo.clear <= (not ctrl.enable) or ctrl.tx_clr; - tx_fifo.we <= '1' when (wren = '1') and (bus_req_i.addr(2) = '1') else '0'; + tx_fifo.we <= '1' when (bus_req_i.we = '1') and (bus_req_i.addr(2) = '1') else '0'; tx_fifo.wdata <= bus_req_i.data; tx_fifo.re <= slink_tx_ready_i; diff --git a/rtl/core/neorv32_spi.vhd b/rtl/core/neorv32_spi.vhd index ccc514b8d..9c6bb1798 100644 --- a/rtl/core/neorv32_spi.vhd +++ b/rtl/core/neorv32_spi.vhd @@ -60,10 +60,6 @@ end neorv32_spi; architecture neorv32_spi_rtl of neorv32_spi is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(spi_size_c); -- low address boundary bit - -- control register -- constant ctrl_en_c : natural := 0; -- r/w: spi enable constant ctrl_cpha_c : natural := 1; -- r/w: spi clock phase @@ -94,12 +90,6 @@ architecture neorv32_spi_rtl of neorv32_spi is -- constant ctrl_busy_c : natural := 31; -- r/-: spi phy busy or tx fifo not empty yet - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- control register -- type ctrl_t is record enable : std_ulogic; @@ -156,12 +146,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = spi_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= spi_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -177,8 +161,8 @@ begin ctrl.irq_tx_empty <= '0'; ctrl.irq_tx_nhalf <= '0'; elsif rising_edge(clk_i) then - if (wren = '1') then - if (addr = spi_ctrl_addr_c) then -- control register + if (bus_req_i.we = '1') then + if (bus_req_i.addr(2) = '0') then -- control register ctrl.enable <= bus_req_i.data(ctrl_en_c); ctrl.cpha <= bus_req_i.data(ctrl_cpha_c); ctrl.cpol <= bus_req_i.data(ctrl_cpol_c); @@ -198,10 +182,10 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= wren or rden; -- bus access acknowledge + bus_rsp_o.ack <= bus_req_i.we or bus_req_i.re; -- bus access acknowledge bus_rsp_o.data <= (others => '0'); - if (rden = '1') then - if (addr = spi_ctrl_addr_c) then -- control register + if (bus_req_i.re = '1') then + if (bus_req_i.addr(2) = '0') then -- control register bus_rsp_o.data(ctrl_en_c) <= ctrl.enable; bus_rsp_o.data(ctrl_cpha_c) <= ctrl.cpha; bus_rsp_o.data(ctrl_cpol_c) <= ctrl.cpol; @@ -221,7 +205,7 @@ begin bus_rsp_o.data(ctrl_fifo_size3_c downto ctrl_fifo_size0_c) <= std_ulogic_vector(to_unsigned(index_size_f(IO_SPI_FIFO), 4)); -- bus_rsp_o.data(ctrl_busy_c) <= rtx_engine.busy or tx_fifo.avail; - else -- data register (spi_rtx_addr_c) + else bus_rsp_o.data(7 downto 0) <= rx_fifo.rdata; end if; end if; @@ -269,7 +253,7 @@ begin ); tx_fifo.clear <= not ctrl.enable; - tx_fifo.we <= '1' when (wren = '1') and (addr = spi_rtx_addr_c) else '0'; + tx_fifo.we <= '1' when (bus_req_i.we = '1') and (bus_req_i.addr(2) = '1') else '0'; tx_fifo.wdata <= bus_req_i.data(7 downto 0); tx_fifo.re <= '1' when (rtx_engine.state = "100") else '0'; @@ -301,7 +285,7 @@ begin rx_fifo.clear <= not ctrl.enable; rx_fifo.wdata <= rtx_engine.sreg; rx_fifo.we <= rtx_engine.done; - rx_fifo.re <= '1' when (rden = '1') and (addr = spi_rtx_addr_c) else '0'; + rx_fifo.re <= '1' when (bus_req_i.re = '1') and (bus_req_i.addr(2) = '1') else '0'; -- IRQ generator -- diff --git a/rtl/core/neorv32_sysinfo.vhd b/rtl/core/neorv32_sysinfo.vhd index 32fea06a8..a61ce4def 100644 --- a/rtl/core/neorv32_sysinfo.vhd +++ b/rtl/core/neorv32_sysinfo.vhd @@ -100,30 +100,12 @@ end neorv32_sysinfo; architecture neorv32_sysinfo_rtl of neorv32_sysinfo is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(sysinfo_size_c); -- low address boundary bit - - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal rden : std_ulogic; - signal wren : std_ulogic; - signal addr : std_ulogic_vector(2 downto 0); - -- system information ROM -- type info_mem_t is array (0 to 7) of std_ulogic_vector(31 downto 0); signal sysinfo : info_mem_t; begin - -- Access Control ------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = sysinfo_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= bus_req_i.addr(index_size_f(sysinfo_size_c)-1 downto 2); - rden <= acc_en and bus_req_i.re; -- read access - wren <= acc_en and bus_req_i.we; -- write access - - -- Construct Info ROM --------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- -- SYSINFO(0): Processor (primary) clock frequency -- @@ -181,10 +163,10 @@ begin sysinfo(3)(31 downto 28) <= (others => '0'); -- d-cache: replacement strategy -- SYSINFO(4): Base address of instruction memory space -- - sysinfo(4) <= ispace_base_c; -- defined in neorv32_package.vhd file + sysinfo(4) <= mem_ispace_base_c; -- defined in neorv32_package.vhd file -- SYSINFO(5): Base address of data memory space -- - sysinfo(5) <= dspace_base_c; -- defined in neorv32_package.vhd file + sysinfo(5) <= mem_dspace_base_c; -- defined in neorv32_package.vhd file -- SYSINFO(6): Size of IMEM in bytes -- sysinfo(6) <= std_ulogic_vector(to_unsigned(MEM_INT_IMEM_SIZE, 32)) when (MEM_INT_IMEM_EN = true) else (others => '0'); @@ -198,11 +180,11 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden; - bus_rsp_o.err <= wren; -- read-only! + bus_rsp_o.ack <= bus_req_i.re; + bus_rsp_o.err <= bus_req_i.we; -- read-only! bus_rsp_o.data <= (others => '0'); - if (rden = '1') then - bus_rsp_o.data <= sysinfo(to_integer(unsigned(addr))); + if (bus_req_i.re = '1') then + bus_rsp_o.data <= sysinfo(to_integer(unsigned(bus_req_i.addr(4 downto 2)))); end if; end if; end process read_access; diff --git a/rtl/core/neorv32_top.vhd b/rtl/core/neorv32_top.vhd index 0b00943e3..79445e332 100644 --- a/rtl/core/neorv32_top.vhd +++ b/rtl/core/neorv32_top.vhd @@ -250,8 +250,9 @@ end neorv32_top; architecture neorv32_top_rtl of neorv32_top is - -- CPU boot configuration -- - constant cpu_boot_addr_c : std_ulogic_vector(31 downto 0) := cond_sel_stdulogicvector_f(INT_BOOTLOADER_EN, boot_rom_base_c, ispace_base_c); + -- auto-configuration -- + constant cpu_boot_addr_c : std_ulogic_vector(31 downto 0) := cond_sel_stdulogicvector_f(INT_BOOTLOADER_EN, mem_boot_base_c, mem_ispace_base_c); + constant io_reg_buf_en_c : boolean := ICACHE_EN or DCACHE_EN; -- reset generator -- signal rstn_ext_sreg, rstn_int_sreg : std_ulogic_vector(3 downto 0); @@ -288,15 +289,9 @@ architecture neorv32_top_rtl of neorv32_top is signal dmi : dmi_t; -- debug core interface (DCI) -- - signal dci_ndmrstn : std_ulogic; - signal dci_halt_req : std_ulogic; + signal dci_ndmrstn, dci_halt_req : std_ulogic; - -- internal bus system -- - type device_ids_t is (DEV_IMEM, DEV_DMEM, DEV_BOOTROM, DEV_WISHBONE, DEV_GPIO, DEV_MTIME, DEV_UART0, DEV_UART1, - DEV_SPI, DEV_TWI, DEV_PWM, DEV_WDT, DEV_TRNG, DEV_CFS, DEV_NEOLED, DEV_SYSINFO, DEV_OCD, - DEV_XIRQ, DEV_GPTMR, DEV_XIP_CT, DEV_XIP_ACC, DEV_ONEWIRE, DEV_SDI, DEV_DMA, DEV_SLINK, DEV_CRC); - - -- core complex -- + -- bus: core complex -- signal cpu_i_req, cpu_d_req : bus_req_t; -- CPU core signal cpu_i_rsp, cpu_d_rsp : bus_rsp_t; -- CPU core signal icache_req, dcache_req : bus_req_t; -- CPU caches @@ -304,321 +299,333 @@ architecture neorv32_top_rtl of neorv32_top is signal core_req : bus_req_t; -- core complex (CPU + caches) signal core_rsp : bus_rsp_t; -- core complex (CPU + caches) - -- core complex + DMA -- + -- bus: core complex + DMA -- signal main_req, dma_req : bus_req_t; -- core complex (CPU + caches + DMA) signal main_rsp, dma_rsp : bus_rsp_t; -- core complex (CPU + caches + DMA) - -- SoC bus -- - type response_bus_t is array (device_ids_t) of bus_rsp_t; - signal soc_req : bus_req_t; -- SoC request bus - signal soc_rsp : bus_rsp_t; -- SoC response bus - signal io_req : bus_req_t; -- request bus for internal IO/Peripheral devices only - signal rsp_bus : response_bus_t; -- global response bus - signal bus_error : std_ulogic; -- global bus error signal + -- bus: main sections -- + signal imem_req, dmem_req, xip_req, boot_req, io_req, xbus_req : bus_req_t; + signal imem_rsp, dmem_rsp, xip_rsp, boot_rsp, io_rsp, xbus_rsp : bus_rsp_t; + + -- bus: IO devices -- + type io_devices_t is ( + IODEV_OCD, IODEV_SYSINFO, IODEV_NEOLED, IODEV_GPIO, IODEV_WDT, IODEV_TRNG, IODEV_TWI, + IODEV_SPI, IODEV_SDI, IODEV_UART1, IODEV_UART0, IODEV_MTIME, IODEV_XIRQ, IODEV_ONEWIRE, + IODEV_GPTMR, IODEV_PWM, IODEV_XIP, IODEV_CRC, IODEV_DMA, IODEV_SLINK, IODEV_CFS + ); + type io_req_bus_t is array (io_devices_t) of bus_req_t; + type io_rsp_bus_t is array (io_devices_t) of bus_rsp_t; + signal io_dev_req : io_req_bus_t; + signal io_dev_rsp : io_rsp_bus_t; -- IRQs -- signal cpu_firq : std_ulogic_vector(15 downto 0); type irq_t is record wdt, uart0_rx, uart0_tx, uart1_rx, uart1_tx, spi, sdi, twi, cfs, neoled, xirq, gptmr, onewire, dma, trng, slink : std_ulogic; end record; - signal firq : irq_t; - - -- misc -- - signal io_acc : std_ulogic; - signal ext_timeout : std_ulogic; - signal ext_access : std_ulogic; - signal xip_access : std_ulogic; - signal xip_enable : std_ulogic; - signal xip_page : std_ulogic_vector(3 downto 0); - signal mtime_irq : std_ulogic; + signal firq : irq_t; + signal mtime_irq : std_ulogic; begin - -- Sanity Checks -------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - assert false report - "NEORV32 PROCESSOR CONFIGURATION: " & - cond_sel_string_f(MEM_INT_IMEM_EN, "IMEM ", "") & - cond_sel_string_f(MEM_INT_DMEM_EN, "DMEM ", "") & - cond_sel_string_f(INT_BOOTLOADER_EN, "BOOTROM ", "") & - cond_sel_string_f(ICACHE_EN, "I-CACHE ", "") & - cond_sel_string_f(DCACHE_EN, "D-CACHE ", "") & - cond_sel_string_f(MEM_EXT_EN, "WISHBONE ", "") & - cond_sel_string_f(ON_CHIP_DEBUGGER_EN, "OCD ", "") & - "+ " & - cond_sel_string_f(boolean(IO_GPIO_NUM > 0), "GPIO ", "") & - cond_sel_string_f(IO_MTIME_EN, "MTIME ", "") & - cond_sel_string_f(IO_UART0_EN, "UART0 ", "") & - cond_sel_string_f(IO_UART1_EN, "UART1 ", "") & - cond_sel_string_f(IO_SPI_EN, "SPI ", "") & - cond_sel_string_f(IO_SDI_EN, "SDI ", "") & - cond_sel_string_f(IO_TWI_EN, "TWI ", "") & - cond_sel_string_f(boolean(IO_PWM_NUM_CH > 0), "PWM ", "") & - cond_sel_string_f(IO_WDT_EN, "WDT ", "") & - cond_sel_string_f(IO_TRNG_EN, "TRNG ", "") & - cond_sel_string_f(IO_CFS_EN, "CFS ", "") & - cond_sel_string_f(IO_NEOLED_EN, "NEOLED ", "") & - cond_sel_string_f(boolean(XIRQ_NUM_CH > 0), "XIRQ ", "") & - cond_sel_string_f(IO_GPTMR_EN, "GPTMR ", "") & - cond_sel_string_f(IO_XIP_EN, "XIP ", "") & - cond_sel_string_f(IO_ONEWIRE_EN, "ONEWIRE ", "") & - cond_sel_string_f(IO_DMA_EN, "DMA ", "") & - cond_sel_string_f(IO_SLINK_EN, "SLINK ", "") & - cond_sel_string_f(IO_CRC_EN, "CRC ", "") & - "" - severity note; - - -- boot configuration -- - assert not (INT_BOOTLOADER_EN = true) report - "NEORV32 PROCESSOR CONFIG NOTE: Boot configuration: Indirect boot via bootloader (processor-internal BOOTROM)." severity note; - assert not ((INT_BOOTLOADER_EN = false) and (MEM_INT_IMEM_EN = true)) report - "NEORV32 PROCESSOR CONFIG NOTE: Boot configuration = direct boot from memory (processor-internal IMEM)." severity note; - 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 (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 (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; - - -- on-chip debugger -- - assert not (ON_CHIP_DEBUGGER_EN = true) report - "NEORV32 PROCESSOR CONFIG NOTE: Implementing on-chip debugger (OCD)." severity note; - - -- caches -- - assert not ((ICACHE_EN = true) and (CPU_EXTENSION_RISCV_Zifencei = false)) report - "NEORV32 CPU CONFIG WARNING! ISA extension is required to perform i-cache memory sync operations." severity warning; - - --- **************************************************************************************************************************** --- Clock and Reset --- **************************************************************************************************************************** - - -- Reset Generator ------------------------------------------------------------------------ - -- ------------------------------------------------------------------------------------------- - reset_generator: process(rstn_i, clk_i) - begin - if (rstn_i = '0') then - rstn_ext_sreg <= (others => '0'); - rstn_int_sreg <= (others => '0'); - rstn_ext <= '0'; - rstn_int <= '0'; - elsif falling_edge(clk_i) then -- inverted clock to release reset _before_ all FFs trigger (rising edge) - -- external reset -- - rstn_ext_sreg <= rstn_ext_sreg(rstn_ext_sreg'left-1 downto 0) & '1'; -- active for at least clock cycles - -- internal reset -- - if (rstn_wdt = '0') or (dci_ndmrstn = '0') then -- sync reset sources + -- ************************************************************************************************************************** + -- Sanity Checks + -- ************************************************************************************************************************** + sanity_checks: + if (true) generate + + assert false report + "NEORV32 PROCESSOR CONFIGURATION: " & + cond_sel_string_f(MEM_INT_IMEM_EN, "IMEM ", "") & + cond_sel_string_f(MEM_INT_DMEM_EN, "DMEM ", "") & + cond_sel_string_f(INT_BOOTLOADER_EN, "BOOTROM ", "") & + cond_sel_string_f(ICACHE_EN, "I-CACHE ", "") & + cond_sel_string_f(DCACHE_EN, "D-CACHE ", "") & + cond_sel_string_f(MEM_EXT_EN, "WISHBONE ", "") & + cond_sel_string_f(ON_CHIP_DEBUGGER_EN, "OCD ", "") & + "+ " & + cond_sel_string_f(boolean(IO_GPIO_NUM > 0), "GPIO ", "") & + cond_sel_string_f(IO_MTIME_EN, "MTIME ", "") & + cond_sel_string_f(IO_UART0_EN, "UART0 ", "") & + cond_sel_string_f(IO_UART1_EN, "UART1 ", "") & + cond_sel_string_f(IO_SPI_EN, "SPI ", "") & + cond_sel_string_f(IO_SDI_EN, "SDI ", "") & + cond_sel_string_f(IO_TWI_EN, "TWI ", "") & + cond_sel_string_f(boolean(IO_PWM_NUM_CH > 0), "PWM ", "") & + cond_sel_string_f(IO_WDT_EN, "WDT ", "") & + cond_sel_string_f(IO_TRNG_EN, "TRNG ", "") & + cond_sel_string_f(IO_CFS_EN, "CFS ", "") & + cond_sel_string_f(IO_NEOLED_EN, "NEOLED ", "") & + cond_sel_string_f(boolean(XIRQ_NUM_CH > 0), "XIRQ ", "") & + cond_sel_string_f(IO_GPTMR_EN, "GPTMR ", "") & + cond_sel_string_f(IO_XIP_EN, "XIP ", "") & + cond_sel_string_f(IO_ONEWIRE_EN, "ONEWIRE ", "") & + cond_sel_string_f(IO_DMA_EN, "DMA ", "") & + cond_sel_string_f(IO_SLINK_EN, "SLINK ", "") & + cond_sel_string_f(IO_CRC_EN, "CRC ", "") & + "" + severity note; + + -- boot configuration -- + assert not (INT_BOOTLOADER_EN = true) report + "NEORV32 PROCESSOR CONFIG NOTE: Boot configuration: Indirect boot via bootloader (processor-internal BOOTROM)." severity note; + assert not ((INT_BOOTLOADER_EN = false) and (MEM_INT_IMEM_EN = true)) report + "NEORV32 PROCESSOR CONFIG NOTE: Boot configuration = direct boot from memory (processor-internal IMEM)." severity note; + 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; + + -- on-chip debugger -- + assert not (ON_CHIP_DEBUGGER_EN = true) report + "NEORV32 PROCESSOR CONFIG NOTE: Implementing on-chip debugger (OCD)." severity note; + + -- caches -- + assert not ((ICACHE_EN = true) and (CPU_EXTENSION_RISCV_Zifencei = false)) report + "NEORV32 CPU CONFIG WARNING! ISA extension is required to perform i-cache memory sync operations." severity warning; + + end generate; -- /sanity_checks + + + -- ************************************************************************************************************************** + -- Clock and Reset Generators + -- ************************************************************************************************************************** + generators: + if (true) generate + + -- Reset Generator ------------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + reset_generator: process(rstn_i, clk_i) + begin + if (rstn_i = '0') then + rstn_ext_sreg <= (others => '0'); rstn_int_sreg <= (others => '0'); - else - rstn_int_sreg <= rstn_int_sreg(rstn_int_sreg'left-1 downto 0) & '1'; -- active for at least clock cycles + rstn_ext <= '0'; + rstn_int <= '0'; + elsif falling_edge(clk_i) then -- inverted clock to release reset _before_ all FFs trigger (rising edge) + -- external reset -- + rstn_ext_sreg <= rstn_ext_sreg(rstn_ext_sreg'left-1 downto 0) & '1'; -- active for at least clock cycles + -- internal reset -- + if (rstn_wdt = '0') or (dci_ndmrstn = '0') then -- sync reset sources + rstn_int_sreg <= (others => '0'); + else + rstn_int_sreg <= rstn_int_sreg(rstn_int_sreg'left-1 downto 0) & '1'; -- active for at least clock cycles + end if; + -- reset nets -- + rstn_ext <= and_reduce_f(rstn_ext_sreg); -- external reset (via reset pin) + rstn_int <= and_reduce_f(rstn_int_sreg); -- internal reset (via reset pin, WDT or OCD) end if; - -- reset nets -- - rstn_ext <= and_reduce_f(rstn_ext_sreg); -- external reset (via reset pin) - rstn_int <= and_reduce_f(rstn_int_sreg); -- internal reset (via reset pin, WDT or OCD) - end if; - end process reset_generator; - - - -- Clock Generator ------------------------------------------------------------------------ - -- ------------------------------------------------------------------------------------------- - clock_generator: process(rstn_int, clk_i) - begin - if (rstn_int = '0') then - clk_gen_en_ff <= '0'; - clk_div <= (others => '0'); - clk_div_ff <= (others => '0'); - elsif rising_edge(clk_i) then - clk_gen_en_ff <= clk_gen_en; - if (clk_gen_en_ff = '1') then - clk_div <= std_ulogic_vector(unsigned(clk_div) + 1); - else -- reset if disabled - clk_div <= (others => '0'); + end process reset_generator; + + + -- Clock Generator ------------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + clock_generator: process(rstn_int, clk_i) + begin + if (rstn_int = '0') then + clk_gen_en_ff <= '0'; + clk_div <= (others => '0'); + clk_div_ff <= (others => '0'); + elsif rising_edge(clk_i) then + clk_gen_en_ff <= clk_gen_en; + if (clk_gen_en_ff = '1') then + clk_div <= std_ulogic_vector(unsigned(clk_div) + 1); + else -- reset if disabled + clk_div <= (others => '0'); + end if; + clk_div_ff <= clk_div; end if; - clk_div_ff <= clk_div; - end if; - end process clock_generator; - - -- clock enables: rising edge detectors -- - clk_gen(clk_div2_c) <= clk_div(0) and (not clk_div_ff(0)); -- CLK/2 - clk_gen(clk_div4_c) <= clk_div(1) and (not clk_div_ff(1)); -- CLK/4 - clk_gen(clk_div8_c) <= clk_div(2) and (not clk_div_ff(2)); -- CLK/8 - clk_gen(clk_div64_c) <= clk_div(5) and (not clk_div_ff(5)); -- CLK/64 - clk_gen(clk_div128_c) <= clk_div(6) and (not clk_div_ff(6)); -- CLK/128 - clk_gen(clk_div1024_c) <= clk_div(9) and (not clk_div_ff(9)); -- CLK/1024 - clk_gen(clk_div2048_c) <= clk_div(10) and (not clk_div_ff(10)); -- CLK/2048 - clk_gen(clk_div4096_c) <= clk_div(11) and (not clk_div_ff(11)); -- CLK/4096 - - -- fresh clocks anyone? -- - clk_gen_en <= cg_en.wdt or cg_en.uart0 or cg_en.uart1 or cg_en.spi or cg_en.twi or cg_en.pwm or - cg_en.cfs or cg_en.neoled or cg_en.gptmr or cg_en.xip or cg_en.onewire; - - --- **************************************************************************************************************************** --- Core Complex --- **************************************************************************************************************************** - - -- CPU Core ------------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_cpu_inst: entity neorv32.neorv32_cpu - generic map ( - -- General -- - HART_ID => HART_ID, - VENDOR_ID => VENDOR_ID, - CPU_BOOT_ADDR => cpu_boot_addr_c, - CPU_DEBUG_PARK_ADDR => dm_park_entry_c, - CPU_DEBUG_EXC_ADDR => dm_exc_entry_c, - -- RISC-V CPU Extensions -- - CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, - CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, - CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, - CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, - CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, - CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, - CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr, - CPU_EXTENSION_RISCV_Zicond => CPU_EXTENSION_RISCV_Zicond, - CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm, - CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, - CPU_EXTENSION_RISCV_Zmmul => CPU_EXTENSION_RISCV_Zmmul, - CPU_EXTENSION_RISCV_Zxcfu => CPU_EXTENSION_RISCV_Zxcfu, - CPU_EXTENSION_RISCV_Sdext => ON_CHIP_DEBUGGER_EN, - CPU_EXTENSION_RISCV_Sdtrig => ON_CHIP_DEBUGGER_EN, - -- Extension Options -- - FAST_MUL_EN => FAST_MUL_EN, - FAST_SHIFT_EN => FAST_SHIFT_EN, - CPU_IPB_ENTRIES => CPU_IPB_ENTRIES, - -- Physical Memory Protection (PMP) -- - PMP_NUM_REGIONS => PMP_NUM_REGIONS, - PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, - -- Hardware Performance Monitors (HPM) -- - HPM_NUM_CNTS => HPM_NUM_CNTS, - HPM_CNT_WIDTH => HPM_CNT_WIDTH - ) - port map ( - -- global control -- - clk_i => clk_i, - rstn_i => rstn_int, - sleep_o => cpu_sleep, - debug_o => cpu_debug, - ifence_o => i_fence, - dfence_o => d_fence, - -- interrupts -- - msi_i => msw_irq_i, - mei_i => mext_irq_i, - mti_i => mtime_irq, - firq_i => cpu_firq, - dbi_i => dci_halt_req, - -- instruction bus interface -- - ibus_req_o => cpu_i_req, - ibus_rsp_i => cpu_i_rsp, - -- data bus interface -- - dbus_req_o => cpu_d_req, - dbus_rsp_i => cpu_d_rsp - ); + end process clock_generator; + + -- clock enables: rising edge detectors -- + clk_gen(clk_div2_c) <= clk_div(0) and (not clk_div_ff(0)); -- CLK/2 + clk_gen(clk_div4_c) <= clk_div(1) and (not clk_div_ff(1)); -- CLK/4 + clk_gen(clk_div8_c) <= clk_div(2) and (not clk_div_ff(2)); -- CLK/8 + clk_gen(clk_div64_c) <= clk_div(5) and (not clk_div_ff(5)); -- CLK/64 + clk_gen(clk_div128_c) <= clk_div(6) and (not clk_div_ff(6)); -- CLK/128 + clk_gen(clk_div1024_c) <= clk_div(9) and (not clk_div_ff(9)); -- CLK/1024 + clk_gen(clk_div2048_c) <= clk_div(10) and (not clk_div_ff(10)); -- CLK/2048 + clk_gen(clk_div4096_c) <= clk_div(11) and (not clk_div_ff(11)); -- CLK/4096 + + -- fresh clocks anyone? -- + clk_gen_en <= cg_en.wdt or cg_en.uart0 or cg_en.uart1 or cg_en.spi or cg_en.twi or cg_en.pwm or + cg_en.cfs or cg_en.neoled or cg_en.gptmr or cg_en.xip or cg_en.onewire; + + end generate; -- /generators + + + -- ************************************************************************************************************************** + -- Core Complex + -- ************************************************************************************************************************** + core_complex: + if (true) generate - -- advanced memory control -- - fence_o <= d_fence; - fencei_o <= i_fence; - - -- fast interrupt requests (FIRQs) -- - cpu_firq(00) <= firq.wdt; -- highest priority - cpu_firq(01) <= firq.cfs; - cpu_firq(02) <= firq.uart0_rx; - cpu_firq(03) <= firq.uart0_tx; - cpu_firq(04) <= firq.uart1_rx; - cpu_firq(05) <= firq.uart1_tx; - cpu_firq(06) <= firq.spi; - cpu_firq(07) <= firq.twi; - cpu_firq(08) <= firq.xirq; - cpu_firq(09) <= firq.neoled; - cpu_firq(10) <= firq.dma; - cpu_firq(11) <= firq.sdi; - cpu_firq(12) <= firq.gptmr; - cpu_firq(13) <= firq.onewire; - cpu_firq(14) <= firq.slink; - cpu_firq(15) <= firq.trng; -- lowest priority - - - -- CPU Instruction Cache ------------------------------------------------------------------ - -- ------------------------------------------------------------------------------------------- - neorv32_icache_inst_true: - if (ICACHE_EN = true) generate - neorv32_icache_inst: entity neorv32.neorv32_icache + -- CPU Core ------------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_cpu_inst: entity neorv32.neorv32_cpu generic map ( - ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, - ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, - ICACHE_NUM_SETS => ICACHE_ASSOCIATIVITY + -- General -- + HART_ID => HART_ID, + VENDOR_ID => VENDOR_ID, + CPU_BOOT_ADDR => cpu_boot_addr_c, + CPU_DEBUG_PARK_ADDR => dm_park_entry_c, + CPU_DEBUG_EXC_ADDR => dm_exc_entry_c, + -- RISC-V CPU Extensions -- + CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, + CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, + CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, + CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, + CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, + CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, + CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr, + CPU_EXTENSION_RISCV_Zicond => CPU_EXTENSION_RISCV_Zicond, + CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm, + CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, + CPU_EXTENSION_RISCV_Zmmul => CPU_EXTENSION_RISCV_Zmmul, + CPU_EXTENSION_RISCV_Zxcfu => CPU_EXTENSION_RISCV_Zxcfu, + CPU_EXTENSION_RISCV_Sdext => ON_CHIP_DEBUGGER_EN, + CPU_EXTENSION_RISCV_Sdtrig => ON_CHIP_DEBUGGER_EN, + -- Extension Options -- + FAST_MUL_EN => FAST_MUL_EN, + FAST_SHIFT_EN => FAST_SHIFT_EN, + CPU_IPB_ENTRIES => CPU_IPB_ENTRIES, + -- Physical Memory Protection (PMP) -- + PMP_NUM_REGIONS => PMP_NUM_REGIONS, + PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, + -- Hardware Performance Monitors (HPM) -- + HPM_NUM_CNTS => HPM_NUM_CNTS, + HPM_CNT_WIDTH => HPM_CNT_WIDTH ) port map ( - clk_i => clk_i, - rstn_i => rstn_int, - clear_i => i_fence, - cpu_req_i => cpu_i_req, - cpu_rsp_o => cpu_i_rsp, - bus_req_o => icache_req, - bus_rsp_i => icache_rsp + -- global control -- + clk_i => clk_i, + rstn_i => rstn_int, + sleep_o => cpu_sleep, + debug_o => cpu_debug, + ifence_o => i_fence, + dfence_o => d_fence, + -- interrupts -- + msi_i => msw_irq_i, + mei_i => mext_irq_i, + mti_i => mtime_irq, + firq_i => cpu_firq, + dbi_i => dci_halt_req, + -- instruction bus interface -- + ibus_req_o => cpu_i_req, + ibus_rsp_i => cpu_i_rsp, + -- data bus interface -- + dbus_req_o => cpu_d_req, + dbus_rsp_i => cpu_d_rsp ); - end generate; - - neorv32_icache_inst_false: - if (ICACHE_EN = false) generate - icache_req <= cpu_i_req; - cpu_i_rsp <= icache_rsp; - end generate; - - -- CPU Data Cache ------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_dcache_inst_true: - if (DCACHE_EN = true) generate - neorv32_dcache_inst: entity neorv32.neorv32_dcache + -- advanced memory control -- + fence_o <= d_fence; + fencei_o <= i_fence; + + -- fast interrupt requests (FIRQs) -- + cpu_firq(00) <= firq.wdt; -- highest priority + cpu_firq(01) <= firq.cfs; + cpu_firq(02) <= firq.uart0_rx; + cpu_firq(03) <= firq.uart0_tx; + cpu_firq(04) <= firq.uart1_rx; + cpu_firq(05) <= firq.uart1_tx; + cpu_firq(06) <= firq.spi; + cpu_firq(07) <= firq.twi; + cpu_firq(08) <= firq.xirq; + cpu_firq(09) <= firq.neoled; + cpu_firq(10) <= firq.dma; + cpu_firq(11) <= firq.sdi; + cpu_firq(12) <= firq.gptmr; + cpu_firq(13) <= firq.onewire; + cpu_firq(14) <= firq.slink; + cpu_firq(15) <= firq.trng; -- lowest priority + + + -- CPU Instruction Cache ------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + neorv32_icache_inst_true: + if (ICACHE_EN = true) generate + neorv32_icache_inst: entity neorv32.neorv32_icache + generic map ( + ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, + ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, + ICACHE_NUM_SETS => ICACHE_ASSOCIATIVITY, + ICACHE_UC_PBEGIN => uncached_begin_c(31 downto 28) + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + clear_i => i_fence, + cpu_req_i => cpu_i_req, + cpu_rsp_o => cpu_i_rsp, + bus_req_o => icache_req, + bus_rsp_i => icache_rsp + ); + end generate; + + neorv32_icache_inst_false: + if (ICACHE_EN = false) generate + icache_req <= cpu_i_req; + cpu_i_rsp <= icache_rsp; + end generate; + + + -- CPU Data Cache ------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_dcache_inst_true: + if (DCACHE_EN = true) generate + neorv32_dcache_inst: entity neorv32.neorv32_dcache + generic map ( + DCACHE_NUM_BLOCKS => DCACHE_NUM_BLOCKS, + DCACHE_BLOCK_SIZE => DCACHE_BLOCK_SIZE, + DCACHE_UC_PBEGIN => uncached_begin_c(31 downto 28) + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + clear_i => d_fence, + cpu_req_i => cpu_d_req, + cpu_rsp_o => cpu_d_rsp, + bus_req_o => dcache_req, + bus_rsp_i => dcache_rsp + ); + end generate; + + neorv32_dcache_inst_false: + if (DCACHE_EN = false) generate + dcache_req <= cpu_d_req; + cpu_d_rsp <= dcache_rsp; + end generate; + + + -- Core Complex Bus Switch ---------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_core_busswitch_inst: entity neorv32.neorv32_busswitch generic map ( - DCACHE_NUM_BLOCKS => DCACHE_NUM_BLOCKS, - DCACHE_BLOCK_SIZE => DCACHE_BLOCK_SIZE, - DCACHE_UC_PBEGIN => "1111" + PORT_A_READ_ONLY => false, + PORT_B_READ_ONLY => true -- i-fetch is read-only ) port map ( - clk_i => clk_i, - rstn_i => rstn_int, - clear_i => d_fence, - cpu_req_i => cpu_d_req, - cpu_rsp_o => cpu_d_rsp, - bus_req_o => dcache_req, - bus_rsp_i => dcache_rsp + clk_i => clk_i, + rstn_i => rstn_int, + a_req_i => dcache_req, + a_rsp_o => dcache_rsp, + b_req_i => icache_req, + b_rsp_o => icache_rsp, + x_req_o => core_req, + x_rsp_i => core_rsp ); - end generate; - - neorv32_dcache_inst_false: - if (DCACHE_EN = false) generate - dcache_req <= cpu_d_req; - cpu_d_rsp <= dcache_rsp; - end generate; - - - -- Core Complex Bus Switch ---------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_core_busswitch_inst: entity neorv32.neorv32_busswitch - generic map ( - PORT_A_READ_ONLY => false, - PORT_B_READ_ONLY => true -- i-fetch is read-only - ) - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - a_req_i => dcache_req, - a_rsp_o => dcache_rsp, - b_req_i => icache_req, - b_rsp_o => icache_rsp, - x_req_o => core_req, - x_rsp_i => core_rsp - ); + end generate; -- /core_complex --- **************************************************************************************************************************** --- Direct Memory Access Controller (DMA) Complex --- **************************************************************************************************************************** - -- DMA controller and according bus switch -- + -- ************************************************************************************************************************** + -- Direct Memory Access Controller (DMA) Complex + -- ************************************************************************************************************************** neorv32_dma_complex_true: if (IO_DMA_EN = true) generate @@ -628,8 +635,8 @@ begin port map ( clk_i => clk_i, rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_DMA), + bus_req_i => io_dev_req(IODEV_DMA), + bus_rsp_o => io_dev_rsp(IODEV_DMA), dma_req_o => dma_req, dma_rsp_i => dma_rsp, firq_i => cpu_firq, @@ -658,786 +665,851 @@ begin neorv32_dma_complex_false: if (IO_DMA_EN = false) generate - rsp_bus(DEV_DMA) <= rsp_terminate_c; - main_req <= core_req; - core_rsp <= main_rsp; - firq.dma <= '0'; - end generate; - - --- **************************************************************************************************************************** --- Bus System --- **************************************************************************************************************************** - - -- Bus Keeper (BUSKEEPER) ----------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_bus_keeper_inst: entity neorv32.neorv32_bus_keeper - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => soc_req, - bus_rsp_i => soc_rsp, - bus_err_o => bus_error, - bus_tmo_i => ext_timeout, - bus_ext_i => ext_access, - bus_xip_i => xip_access - ); - - -- global bus response --- - bus_response: process(rsp_bus) - variable tmp_v : bus_rsp_t; - begin - tmp_v := rsp_terminate_c; - for i in rsp_bus'range loop -- OR all response signals - tmp_v.data := tmp_v.data or rsp_bus(i).data; - tmp_v.ack := tmp_v.ack or rsp_bus(i).ack; - tmp_v.err := tmp_v.err or rsp_bus(i).err; - end loop; - soc_rsp <= tmp_v; - end process; - - -- central SoC bus -- - soc_req <= main_req; - main_rsp.data <= soc_rsp.data; - main_rsp.ack <= soc_rsp.ack; - main_rsp.err <= bus_error; -- global bus error (buskeeper -> core) - - --- **************************************************************************************************************************** --- Memory System --- **************************************************************************************************************************** - - -- Processor-Internal Instruction Memory (IMEM) ------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_int_imem_inst_true: - if (MEM_INT_IMEM_EN = true) and (MEM_INT_IMEM_SIZE > 0) generate - neorv32_int_imem_inst: entity neorv32.neorv32_imem - generic map ( - IMEM_BASE => imem_base_c, - IMEM_SIZE => MEM_INT_IMEM_SIZE, - IMEM_AS_IROM => not INT_BOOTLOADER_EN - ) - port map ( - clk_i => clk_i, - bus_req_i => soc_req, - bus_rsp_o => rsp_bus(DEV_IMEM) - ); + io_dev_rsp(IODEV_DMA) <= rsp_terminate_c; + main_req <= core_req; + core_rsp <= main_rsp; + firq.dma <= '0'; end generate; - neorv32_int_imem_inst_false: - if (MEM_INT_IMEM_EN = false) or (MEM_INT_IMEM_SIZE = 0) generate - rsp_bus(DEV_IMEM) <= rsp_terminate_c; - end generate; - -- Processor-Internal Data Memory (DMEM) -------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_int_dmem_inst_true: - if (MEM_INT_DMEM_EN = true) and (MEM_INT_DMEM_SIZE > 0) generate - neorv32_int_dmem_inst: entity neorv32.neorv32_dmem + -- ************************************************************************************************************************** + -- Address Region Gateway + -- ************************************************************************************************************************** + neorv32_gateway_inst: entity neorv32.neorv32_gateway generic map ( - DMEM_BASE => dmem_base_c, - DMEM_SIZE => MEM_INT_DMEM_SIZE - ) - port map ( - clk_i => clk_i, - bus_req_i => soc_req, - bus_rsp_o => rsp_bus(DEV_DMEM) - ); - end generate; - - neorv32_int_dmem_inst_false: - if (MEM_INT_DMEM_EN = false) or (MEM_INT_DMEM_SIZE = 0) generate - rsp_bus(DEV_DMEM) <= rsp_terminate_c; - end generate; - - - -- Processor-Internal Bootloader ROM (BOOTROM) -------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_boot_rom_inst_true: - if (INT_BOOTLOADER_EN = true) generate - neorv32_boot_rom_inst: entity neorv32.neorv32_boot_rom - generic map ( - BOOTROM_BASE => boot_rom_base_c - ) - port map ( - clk_i => clk_i, - bus_req_i => soc_req, - bus_rsp_o => rsp_bus(DEV_BOOTROM) - ); - end generate; - - neorv32_boot_rom_inst_false: - if (INT_BOOTLOADER_EN = false) generate - rsp_bus(DEV_BOOTROM) <= rsp_terminate_c; - end generate; - - - -- External Wishbone Gateway (WISHBONE) --------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_wishbone_inst_true: - if (MEM_EXT_EN = true) generate - neorv32_wishbone_inst: entity neorv32.neorv32_wishbone - generic map ( - -- Internal instruction memory -- - MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, - MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, - -- Internal data memory -- - MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, - MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, - -- Interface Configuration -- - BUS_TIMEOUT => MEM_EXT_TIMEOUT, - PIPE_MODE => MEM_EXT_PIPE_MODE, - BIG_ENDIAN => MEM_EXT_BIG_ENDIAN, - ASYNC_RX => MEM_EXT_ASYNC_RX, - ASYNC_TX => MEM_EXT_ASYNC_TX + TIMEOUT => max_proc_int_response_time_c, + -- IMEM port -- + IMEM_ENABLE => MEM_INT_IMEM_EN, + IMEM_BASE => mem_ispace_base_c, + IMEM_SIZE => MEM_INT_IMEM_SIZE, + -- DMEM port -- + DMEM_ENABLE => MEM_INT_DMEM_EN, + DMEM_BASE => mem_dspace_base_c, + DMEM_SIZE => MEM_INT_DMEM_SIZE, + -- XIP port -- + XIP_ENABLE => IO_XIP_EN, + XIP_BASE => mem_xip_base_c, + XIP_SIZE => mem_xip_size_c, + -- BOOT ROM port -- + BOOT_ENABLE => INT_BOOTLOADER_EN, + BOOT_BASE => mem_boot_base_c, + BOOT_SIZE => mem_boot_size_c, + -- IO port -- + IO_ENABLE => true, + IO_REQ_REG => io_reg_buf_en_c, + IO_RSP_REG => io_reg_buf_en_c, + IO_BASE => mem_io_base_c, + IO_SIZE => mem_io_size_c, + -- EXT port -- + EXT_ENABLE => MEM_EXT_EN ) port map ( -- global control -- clk_i => clk_i, rstn_i => rstn_int, - bus_req_i => soc_req, - bus_rsp_o => rsp_bus(DEV_WISHBONE), - tmo_o => ext_timeout, - ext_o => ext_access, - xip_en_i => xip_enable, - xip_page_i => xip_page, - -- - wb_tag_o => wb_tag_o, - wb_adr_o => wb_adr_o, - wb_dat_i => wb_dat_i, - wb_dat_o => wb_dat_o, - wb_we_o => wb_we_o, - wb_sel_o => wb_sel_o, - wb_stb_o => wb_stb_o, - wb_cyc_o => wb_cyc_o, - wb_ack_i => wb_ack_i, - wb_err_i => wb_err_i - ); - end generate; - - neorv32_wishbone_inst_false: - if (MEM_EXT_EN = false) generate - rsp_bus(DEV_WISHBONE) <= rsp_terminate_c; - ext_timeout <= '0'; - ext_access <= '0'; - wb_adr_o <= (others => '0'); - wb_dat_o <= (others => '0'); - wb_we_o <= '0'; - wb_sel_o <= (others => '0'); - wb_stb_o <= '0'; - wb_cyc_o <= '0'; - wb_tag_o <= (others => '0'); - end generate; - - - -- Execute In Place Module (XIP) ---------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_xip_inst_true: - if (IO_XIP_EN = true) generate - neorv32_xip_inst: entity neorv32.neorv32_xip - port map ( - -- global control -- - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_XIP_CT), - xip_req_i => soc_req, - xip_rsp_o => rsp_bus(DEV_XIP_ACC), - xip_en_o => xip_enable, - xip_acc_o => xip_access, - xip_page_o => xip_page, - clkgen_en_o => cg_en.xip, - clkgen_i => clk_gen, - spi_csn_o => xip_csn_o, - spi_clk_o => xip_clk_o, - spi_dat_i => xip_dat_i, - spi_dat_o => xip_dat_o - ); - end generate; - - neorv32_xip_inst_false: - if (IO_XIP_EN = false) generate - rsp_bus(DEV_XIP_CT) <= rsp_terminate_c; - rsp_bus(DEV_XIP_ACC) <= rsp_terminate_c; - xip_enable <= '0'; - xip_access <= '0'; - xip_page <= (others => '0'); - cg_en.xip <= '0'; - xip_csn_o <= '1'; - xip_clk_o <= '0'; - xip_dat_o <= '0'; - end generate; - - --- **************************************************************************************************************************** --- IO/Peripheral Modules --- **************************************************************************************************************************** - - -- IO Gateway ----------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - io_gateway: process(soc_req, io_acc) - begin - io_req <= soc_req; - io_req.re <= io_acc and soc_req.re and (not soc_req.src); -- PMA: read access only from data interface - io_req.we <= io_acc and soc_req.we and and_reduce_f(soc_req.ben); -- PMA: full-word write accesses only - end process io_gateway; - - -- IO access? -- - io_acc <= '1' when (soc_req.addr(31 downto index_size_f(io_size_c)) = io_base_c(31 downto index_size_f(io_size_c))) else '0'; - - - -- Custom Functions Subsystem (CFS) ------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_cfs_inst_true: - if (IO_CFS_EN = true) generate - neorv32_cfs_inst: entity neorv32.neorv32_cfs - generic map ( - CFS_CONFIG => IO_CFS_CONFIG, - CFS_IN_SIZE => IO_CFS_IN_SIZE, - CFS_OUT_SIZE => IO_CFS_OUT_SIZE - ) - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_CFS), - clkgen_en_o => cg_en.cfs, - clkgen_i => clk_gen, - irq_o => firq.cfs, - cfs_in_i => cfs_in_i, - cfs_out_o => cfs_out_o - ); - end generate; - - neorv32_cfs_inst_false: - if (IO_CFS_EN = false) generate - rsp_bus(DEV_CFS) <= rsp_terminate_c; - cg_en.cfs <= '0'; - firq.cfs <= '0'; - cfs_out_o <= (others => '0'); - end generate; - - - -- Serial Data Interface (SDI) ------------------------------------------------------------ - -- ------------------------------------------------------------------------------------------- - neorv32_sdi_inst_true: - if (IO_SDI_EN = true) generate - neorv32_SDI_inst: entity neorv32.neorv32_sdi - generic map ( - RTX_FIFO => IO_SDI_FIFO - ) - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_SDI), - sdi_csn_i => sdi_csn_i, - sdi_clk_i => sdi_clk_i, - sdi_dat_i => sdi_dat_i, - sdi_dat_o => sdi_dat_o, - irq_o => firq.sdi - ); - end generate; - - neorv32_sdi_inst_false: - if (IO_SDI_EN = false) generate - rsp_bus(DEV_SDI) <= rsp_terminate_c; - sdi_dat_o <= '0'; - firq.sdi <= '0'; - end generate; - - - -- General Purpose Input/Output Port (GPIO) ----------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_gpio_inst_true: - if (IO_GPIO_NUM > 0) generate - neorv32_gpio_inst: entity neorv32.neorv32_gpio - generic map ( - GPIO_NUM => IO_GPIO_NUM - ) - port map ( - -- host access -- - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_GPIO), - gpio_o => gpio_o, - gpio_i => gpio_i - ); - end generate; - - neorv32_gpio_inst_false: - if (IO_GPIO_NUM = 0) generate - rsp_bus(DEV_GPIO) <= rsp_terminate_c; - gpio_o <= (others => '0'); - end generate; - - - -- Watch Dog Timer (WDT) ------------------------------------------------------------------ - -- ------------------------------------------------------------------------------------------- - neorv32_wdt_inst_true: - if (IO_WDT_EN = true) generate - neorv32_wdt_inst: entity neorv32.neorv32_wdt - port map ( - clk_i => clk_i, - rstn_ext_i => rstn_ext, - rstn_int_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_WDT), - cpu_debug_i => cpu_debug, - cpu_sleep_i => cpu_sleep, - clkgen_en_o => cg_en.wdt, - clkgen_i => clk_gen, - irq_o => firq.wdt, - rstn_o => rstn_wdt - ); - end generate; - - neorv32_wdt_inst_false: - if (IO_WDT_EN = false) generate - rsp_bus(DEV_WDT) <= rsp_terminate_c; - firq.wdt <= '0'; - rstn_wdt <= '1'; - cg_en.wdt <= '0'; - end generate; - - - -- Machine System Timer (MTIME) ----------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_mtime_inst_true: - if (IO_MTIME_EN = true) generate - neorv32_mtime_inst: entity neorv32.neorv32_mtime - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_MTIME), - irq_o => mtime_irq - ); - end generate; - - neorv32_mtime_inst_false: - if (IO_MTIME_EN = false) generate - rsp_bus(DEV_MTIME) <= rsp_terminate_c; - mtime_irq <= mtime_irq_i; - end generate; - - - -- Primary Universal Asynchronous Receiver/Transmitter (UART0) ---------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_uart0_inst_true: - if (IO_UART0_EN = true) generate - neorv32_uart0_inst: entity neorv32.neorv32_uart - generic map ( - UART_PRIMARY => true, - UART_RX_FIFO => IO_UART0_RX_FIFO, - UART_TX_FIFO => IO_UART0_TX_FIFO - ) - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_UART0), - clkgen_en_o => cg_en.uart0, - clkgen_i => clk_gen, - uart_txd_o => uart0_txd_o, - uart_rxd_i => uart0_rxd_i, - uart_rts_o => uart0_rts_o, - uart_cts_i => uart0_cts_i, - irq_rx_o => firq.uart0_rx, - irq_tx_o => firq.uart0_tx - ); - end generate; - - neorv32_uart0_inst_false: - if (IO_UART0_EN = false) generate - rsp_bus(DEV_UART0) <= rsp_terminate_c; - uart0_txd_o <= '0'; - uart0_rts_o <= '1'; - cg_en.uart0 <= '0'; - firq.uart0_rx <= '0'; - firq.uart0_tx <= '0'; - end generate; - - - -- Secondary Universal Asynchronous Receiver/Transmitter (UART1) -------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_uart1_inst_true: - if (IO_UART1_EN = true) generate - neorv32_uart1_inst: entity neorv32.neorv32_uart - generic map ( - UART_PRIMARY => false, - UART_RX_FIFO => IO_UART1_RX_FIFO, - UART_TX_FIFO => IO_UART1_TX_FIFO - ) - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_UART1), - clkgen_en_o => cg_en.uart1, - clkgen_i => clk_gen, - uart_txd_o => uart1_txd_o, - uart_rxd_i => uart1_rxd_i, - uart_rts_o => uart1_rts_o, - uart_cts_i => uart1_cts_i, - irq_rx_o => firq.uart1_rx, - irq_tx_o => firq.uart1_tx + -- host port -- + main_req_i => main_req, + main_rsp_o => main_rsp, + -- section ports -- + imem_req_o => imem_req, + imem_rsp_i => imem_rsp, + dmem_req_o => dmem_req, + dmem_rsp_i => dmem_rsp, + xip_req_o => xip_req, + xip_rsp_i => xip_rsp, + boot_req_o => boot_req, + boot_rsp_i => boot_rsp, + io_req_o => io_req, + io_rsp_i => io_rsp, + ext_req_o => xbus_req, + ext_rsp_i => xbus_rsp ); - end generate; - neorv32_uart1_inst_false: - if (IO_UART1_EN = false) generate - rsp_bus(DEV_UART1) <= rsp_terminate_c; - uart1_txd_o <= '0'; - uart1_rts_o <= '1'; - cg_en.uart1 <= '0'; - firq.uart1_rx <= '0'; - firq.uart1_tx <= '0'; - end generate; + -- ************************************************************************************************************************** + -- Memory System + -- ************************************************************************************************************************** + memory_system: + if (true) generate - -- Serial Peripheral Interface (SPI) ------------------------------------------------------ - -- ------------------------------------------------------------------------------------------- - neorv32_spi_inst_true: - if (IO_SPI_EN = true) generate - neorv32_spi_inst: entity neorv32.neorv32_spi - generic map ( - IO_SPI_FIFO => IO_SPI_FIFO - ) - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_SPI), - clkgen_en_o => cg_en.spi, - clkgen_i => clk_gen, - spi_clk_o => spi_clk_o, - spi_dat_o => spi_dat_o, - spi_dat_i => spi_dat_i, - spi_csn_o => spi_csn_o, - irq_o => firq.spi - ); - end generate; - - neorv32_spi_inst_false: - if (IO_SPI_EN = false) generate - rsp_bus(DEV_SPI) <= rsp_terminate_c; - spi_clk_o <= '0'; - spi_dat_o <= '0'; - spi_csn_o <= (others => '1'); - cg_en.spi <= '0'; - firq.spi <= '0'; - end generate; - - - -- Two-Wire Interface (TWI) --------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_twi_inst_true: - if (IO_TWI_EN = true) generate - neorv32_twi_inst: entity neorv32.neorv32_twi - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_TWI), - clkgen_en_o => cg_en.twi, - clkgen_i => clk_gen, - twi_sda_i => twi_sda_i, - twi_sda_o => twi_sda_o, - twi_scl_i => twi_scl_i, - twi_scl_o => twi_scl_o, - irq_o => firq.twi - ); - end generate; - - neorv32_twi_inst_false: - if (IO_TWI_EN = false) generate - rsp_bus(DEV_TWI) <= rsp_terminate_c; - twi_sda_o <= '1'; - twi_scl_o <= '1'; - cg_en.twi <= '0'; - firq.twi <= '0'; - end generate; - - - -- Pulse-Width Modulation Controller (PWM) ------------------------------------------------ - -- ------------------------------------------------------------------------------------------- - neorv32_pwm_inst_true: - if (IO_PWM_NUM_CH > 0) generate - neorv32_pwm_inst: entity neorv32.neorv32_pwm - generic map ( - NUM_CHANNELS => IO_PWM_NUM_CH - ) - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_PWM), - clkgen_en_o => cg_en.pwm, - clkgen_i => clk_gen, - pwm_o => pwm_o - ); - end generate; + -- Processor-Internal Instruction Memory (IMEM) ------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_int_imem_inst_true: + if (MEM_INT_IMEM_EN = true) and (MEM_INT_IMEM_SIZE > 0) generate + neorv32_int_imem_inst: entity neorv32.neorv32_imem + generic map ( + IMEM_SIZE => MEM_INT_IMEM_SIZE, + IMEM_AS_IROM => not INT_BOOTLOADER_EN + ) + port map ( + clk_i => clk_i, + bus_req_i => imem_req, + bus_rsp_o => imem_rsp + ); + end generate; - neorv32_pwm_inst_false: - if (IO_PWM_NUM_CH = 0) generate - rsp_bus(DEV_PWM) <= rsp_terminate_c; - cg_en.pwm <= '0'; - pwm_o <= (others => '0'); - end generate; + neorv32_int_imem_inst_false: + if (MEM_INT_IMEM_EN = false) or (MEM_INT_IMEM_SIZE = 0) generate + imem_rsp <= rsp_terminate_c; + end generate; - -- True Random Number Generator (TRNG) ---------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_trng_inst_true: - if (IO_TRNG_EN = true) generate - neorv32_trng_inst: entity neorv32.neorv32_trng - generic map ( - IO_TRNG_FIFO => IO_TRNG_FIFO - ) - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_TRNG), - irq_o => firq.trng - ); - end generate; + -- Processor-Internal Data Memory (DMEM) -------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_int_dmem_inst_true: + if (MEM_INT_DMEM_EN = true) and (MEM_INT_DMEM_SIZE > 0) generate + neorv32_int_dmem_inst: entity neorv32.neorv32_dmem + generic map ( + DMEM_SIZE => MEM_INT_DMEM_SIZE + ) + port map ( + clk_i => clk_i, + bus_req_i => dmem_req, + bus_rsp_o => dmem_rsp + ); + end generate; - neorv32_trng_inst_false: - if (IO_TRNG_EN = false) generate - rsp_bus(DEV_TRNG) <= rsp_terminate_c; - firq.trng <= '0'; - end generate; + neorv32_int_dmem_inst_false: + if (MEM_INT_DMEM_EN = false) or (MEM_INT_DMEM_SIZE = 0) generate + dmem_rsp <= rsp_terminate_c; + end generate; - -- Smart LED (WS2811/WS2812) Interface (NEOLED) ------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_neoled_inst_true: - if (IO_NEOLED_EN = true) generate - neorv32_neoled_inst: entity neorv32.neorv32_neoled - generic map ( - FIFO_DEPTH => IO_NEOLED_TX_FIFO - ) - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_NEOLED), - clkgen_en_o => cg_en.neoled, - clkgen_i => clk_gen, - irq_o => firq.neoled, - neoled_o => neoled_o - ); - end generate; + -- Processor-Internal Bootloader ROM (BOOTROM) -------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_boot_rom_inst_true: + if (INT_BOOTLOADER_EN = true) generate + neorv32_boot_rom_inst: entity neorv32.neorv32_boot_rom + port map ( + clk_i => clk_i, + bus_req_i => boot_req, + bus_rsp_o => boot_rsp + ); + end generate; - neorv32_neoled_inst_false: - if (IO_NEOLED_EN = false) generate - rsp_bus(DEV_NEOLED) <= rsp_terminate_c; - cg_en.neoled <= '0'; - firq.neoled <= '0'; - neoled_o <= '0'; - end generate; + neorv32_boot_rom_inst_false: + if (INT_BOOTLOADER_EN = false) generate + boot_rsp <= rsp_terminate_c; + end generate; - -- External Interrupt Controller (XIRQ) --------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_xirq_inst_true: - if (XIRQ_NUM_CH > 0) generate - neorv32_xirq_inst: entity neorv32.neorv32_xirq + -- Execute In Place Module (XIP) ---------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_xip_inst_true: + if (IO_XIP_EN = true) generate + neorv32_xip_inst: entity neorv32.neorv32_xip + port map ( + -- global control -- + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_XIP), + bus_rsp_o => io_dev_rsp(IODEV_XIP), + xip_req_i => xip_req, + xip_rsp_o => xip_rsp, + clkgen_en_o => cg_en.xip, + clkgen_i => clk_gen, + spi_csn_o => xip_csn_o, + spi_clk_o => xip_clk_o, + spi_dat_i => xip_dat_i, + spi_dat_o => xip_dat_o + ); + end generate; + + neorv32_xip_inst_false: + if (IO_XIP_EN = false) generate + io_dev_rsp(IODEV_XIP) <= rsp_terminate_c; + xip_rsp <= rsp_terminate_c; + cg_en.xip <= '0'; + xip_csn_o <= '1'; + xip_clk_o <= '0'; + xip_dat_o <= '0'; + end generate; + + + -- External Wishbone Gateway (WISHBONE) --------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_wishbone_inst_true: + if (MEM_EXT_EN = true) generate + neorv32_wishbone_inst: entity neorv32.neorv32_wishbone + generic map ( + BUS_TIMEOUT => MEM_EXT_TIMEOUT, + PIPE_MODE => MEM_EXT_PIPE_MODE, + BIG_ENDIAN => MEM_EXT_BIG_ENDIAN, + ASYNC_RX => MEM_EXT_ASYNC_RX, + ASYNC_TX => MEM_EXT_ASYNC_TX + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => xbus_req, + bus_rsp_o => xbus_rsp, + -- + wb_tag_o => wb_tag_o, + wb_adr_o => wb_adr_o, + wb_dat_i => wb_dat_i, + wb_dat_o => wb_dat_o, + wb_we_o => wb_we_o, + wb_sel_o => wb_sel_o, + wb_stb_o => wb_stb_o, + wb_cyc_o => wb_cyc_o, + wb_ack_i => wb_ack_i, + wb_err_i => wb_err_i + ); + end generate; + + neorv32_wishbone_inst_false: + if (MEM_EXT_EN = false) generate + xbus_rsp <= rsp_terminate_c; + wb_adr_o <= (others => '0'); + wb_dat_o <= (others => '0'); + wb_we_o <= '0'; + wb_sel_o <= (others => '0'); + wb_stb_o <= '0'; + wb_cyc_o <= '0'; + wb_tag_o <= (others => '0'); + end generate; + + end generate; -- /memory_system + + + -- ************************************************************************************************************************** + -- IO/Peripheral Modules + -- ************************************************************************************************************************** + io_system: + if (true) generate + + -- IO Switch ------------------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + io_switch_inst: entity neorv32.io_switch generic map ( - XIRQ_NUM_CH => XIRQ_NUM_CH, - XIRQ_TRIGGER_TYPE => XIRQ_TRIGGER_TYPE, - XIRQ_TRIGGER_POLARITY => XIRQ_TRIGGER_POLARITY + DEV_SIZE => iodev_size_c, -- size of a single IO device + -- device base addresses -- + DEV_00_BASE => base_io_dm_c, + DEV_01_BASE => base_io_sysinfo_c, + DEV_02_BASE => base_io_neoled_c, + DEV_03_BASE => base_io_gpio_c, + DEV_04_BASE => base_io_wdt_c, + DEV_05_BASE => base_io_trng_c, + DEV_06_BASE => base_io_twi_c, + DEV_07_BASE => base_io_spi_c, + DEV_08_BASE => base_io_sdi_c, + DEV_09_BASE => base_io_uart1_c, + DEV_10_BASE => base_io_uart0_c, + DEV_11_BASE => base_io_mtime_c, + DEV_12_BASE => base_io_xirq_c, + DEV_13_BASE => base_io_onewire_c, + DEV_14_BASE => base_io_gptmr_c, + DEV_15_BASE => base_io_pwm_c, + DEV_16_BASE => base_io_xip_c, + DEV_17_BASE => base_io_crc_c, + DEV_18_BASE => base_io_dma_c, + DEV_19_BASE => base_io_slink_c, + DEV_20_BASE => base_io_cfs_c ) port map ( - -- host access -- - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_XIRQ), - xirq_i => xirq_i, - cpu_irq_o => firq.xirq - ); - end generate; - - neorv32_xirq_inst_false: - if (XIRQ_NUM_CH = 0) generate - rsp_bus(DEV_XIRQ) <= rsp_terminate_c; - firq.xirq <= '0'; - end generate; - - - -- General Purpose Timer (GPTMR) ---------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_gptmr_inst_true: - if (IO_GPTMR_EN = true) generate - neorv32_gptmr_inst: entity neorv32.neorv32_gptmr - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_GPTMR), - clkgen_en_o => cg_en.gptmr, - clkgen_i => clk_gen, - irq_o => firq.gptmr - ); - end generate; - - neorv32_gptmr_inst_false: - if (IO_GPTMR_EN = false) generate - rsp_bus(DEV_GPTMR) <= rsp_terminate_c; - cg_en.gptmr <= '0'; - firq.gptmr <= '0'; - end generate; - - - -- 1-Wire Interface Controller (ONEWIRE) -------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_onewire_inst_true: - if (IO_ONEWIRE_EN = true) generate - neorv32_onewire_inst: entity neorv32.neorv32_onewire - port map ( - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_ONEWIRE), - clkgen_en_o => cg_en.onewire, - clkgen_i => clk_gen, - onewire_i => onewire_i, - onewire_o => onewire_o, - irq_o => firq.onewire + -- host port -- + main_req_i => io_req, + main_rsp_o => io_rsp, + -- device ports -- + dev_req_o(00) => io_dev_req(IODEV_OCD), + dev_req_o(01) => io_dev_req(IODEV_SYSINFO), + dev_req_o(02) => io_dev_req(IODEV_NEOLED), + dev_req_o(03) => io_dev_req(IODEV_GPIO), + dev_req_o(04) => io_dev_req(IODEV_WDT), + dev_req_o(05) => io_dev_req(IODEV_TRNG), + dev_req_o(06) => io_dev_req(IODEV_TWI), + dev_req_o(07) => io_dev_req(IODEV_SPI), + dev_req_o(08) => io_dev_req(IODEV_SDI), + dev_req_o(09) => io_dev_req(IODEV_UART1), + dev_req_o(10) => io_dev_req(IODEV_UART0), + dev_req_o(11) => io_dev_req(IODEV_MTIME), + dev_req_o(12) => io_dev_req(IODEV_XIRQ), + dev_req_o(13) => io_dev_req(IODEV_ONEWIRE), + dev_req_o(14) => io_dev_req(IODEV_GPTMR), + dev_req_o(15) => io_dev_req(IODEV_PWM), + dev_req_o(16) => io_dev_req(IODEV_XIP), + dev_req_o(17) => io_dev_req(IODEV_CRC), + dev_req_o(18) => io_dev_req(IODEV_DMA), + dev_req_o(19) => io_dev_req(IODEV_SLINK), + dev_req_o(20) => io_dev_req(IODEV_CFS), + -- + dev_rsp_i(00) => io_dev_rsp(IODEV_OCD), + dev_rsp_i(01) => io_dev_rsp(IODEV_SYSINFO), + dev_rsp_i(02) => io_dev_rsp(IODEV_NEOLED), + dev_rsp_i(03) => io_dev_rsp(IODEV_GPIO), + dev_rsp_i(04) => io_dev_rsp(IODEV_WDT), + dev_rsp_i(05) => io_dev_rsp(IODEV_TRNG), + dev_rsp_i(06) => io_dev_rsp(IODEV_TWI), + dev_rsp_i(07) => io_dev_rsp(IODEV_SPI), + dev_rsp_i(08) => io_dev_rsp(IODEV_SDI), + dev_rsp_i(09) => io_dev_rsp(IODEV_UART1), + dev_rsp_i(10) => io_dev_rsp(IODEV_UART0), + dev_rsp_i(11) => io_dev_rsp(IODEV_MTIME), + dev_rsp_i(12) => io_dev_rsp(IODEV_XIRQ), + dev_rsp_i(13) => io_dev_rsp(IODEV_ONEWIRE), + dev_rsp_i(14) => io_dev_rsp(IODEV_GPTMR), + dev_rsp_i(15) => io_dev_rsp(IODEV_PWM), + dev_rsp_i(16) => io_dev_rsp(IODEV_XIP), + dev_rsp_i(17) => io_dev_rsp(IODEV_CRC), + dev_rsp_i(18) => io_dev_rsp(IODEV_DMA), + dev_rsp_i(19) => io_dev_rsp(IODEV_SLINK), + dev_rsp_i(20) => io_dev_rsp(IODEV_CFS) ); - end generate; - - neorv32_onewire_inst_false: - if (IO_ONEWIRE_EN = false) generate - rsp_bus(DEV_ONEWIRE) <= rsp_terminate_c; - onewire_o <= '1'; - cg_en.onewire <= '0'; - firq.onewire <= '0'; - end generate; - -- Stream Link Interface (SLINK) ---------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_slink_inst_true: - if (IO_SLINK_EN = true) generate - neorv32_slink_inst: entity neorv32.neorv32_slink + -- Custom Functions Subsystem (CFS) ------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_cfs_inst_true: + if (IO_CFS_EN = true) generate + neorv32_cfs_inst: entity neorv32.neorv32_cfs + generic map ( + CFS_CONFIG => IO_CFS_CONFIG, + CFS_IN_SIZE => IO_CFS_IN_SIZE, + CFS_OUT_SIZE => IO_CFS_OUT_SIZE + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_CFS), + bus_rsp_o => io_dev_rsp(IODEV_CFS), + clkgen_en_o => cg_en.cfs, + clkgen_i => clk_gen, + irq_o => firq.cfs, + cfs_in_i => cfs_in_i, + cfs_out_o => cfs_out_o + ); + end generate; + + neorv32_cfs_inst_false: + if (IO_CFS_EN = false) generate + io_dev_rsp(IODEV_CFS) <= rsp_terminate_c; + cg_en.cfs <= '0'; + firq.cfs <= '0'; + cfs_out_o <= (others => '0'); + end generate; + + + -- Serial Data Interface (SDI) ------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + neorv32_sdi_inst_true: + if (IO_SDI_EN = true) generate + neorv32_SDI_inst: entity neorv32.neorv32_sdi + generic map ( + RTX_FIFO => IO_SDI_FIFO + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_SDI), + bus_rsp_o => io_dev_rsp(IODEV_SDI), + sdi_csn_i => sdi_csn_i, + sdi_clk_i => sdi_clk_i, + sdi_dat_i => sdi_dat_i, + sdi_dat_o => sdi_dat_o, + irq_o => firq.sdi + ); + end generate; + + neorv32_sdi_inst_false: + if (IO_SDI_EN = false) generate + io_dev_rsp(IODEV_SDI) <= rsp_terminate_c; + sdi_dat_o <= '0'; + firq.sdi <= '0'; + end generate; + + + -- General Purpose Input/Output Port (GPIO) ----------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_gpio_inst_true: + if (IO_GPIO_NUM > 0) generate + neorv32_gpio_inst: entity neorv32.neorv32_gpio + generic map ( + GPIO_NUM => IO_GPIO_NUM + ) + port map ( + -- host access -- + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_GPIO), + bus_rsp_o => io_dev_rsp(IODEV_GPIO), + gpio_o => gpio_o, + gpio_i => gpio_i + ); + end generate; + + neorv32_gpio_inst_false: + if (IO_GPIO_NUM = 0) generate + io_dev_rsp(IODEV_GPIO) <= rsp_terminate_c; + gpio_o <= (others => '0'); + end generate; + + + -- Watch Dog Timer (WDT) ------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + neorv32_wdt_inst_true: + if (IO_WDT_EN = true) generate + neorv32_wdt_inst: entity neorv32.neorv32_wdt + port map ( + clk_i => clk_i, + rstn_ext_i => rstn_ext, + rstn_int_i => rstn_int, + bus_req_i => io_dev_req(IODEV_WDT), + bus_rsp_o => io_dev_rsp(IODEV_WDT), + cpu_debug_i => cpu_debug, + cpu_sleep_i => cpu_sleep, + clkgen_en_o => cg_en.wdt, + clkgen_i => clk_gen, + irq_o => firq.wdt, + rstn_o => rstn_wdt + ); + end generate; + + neorv32_wdt_inst_false: + if (IO_WDT_EN = false) generate + io_dev_rsp(IODEV_WDT) <= rsp_terminate_c; + firq.wdt <= '0'; + rstn_wdt <= '1'; + cg_en.wdt <= '0'; + end generate; + + + -- Machine System Timer (MTIME) ----------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_mtime_inst_true: + if (IO_MTIME_EN = true) generate + neorv32_mtime_inst: entity neorv32.neorv32_mtime + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_MTIME), + bus_rsp_o => io_dev_rsp(IODEV_MTIME), + irq_o => mtime_irq + ); + end generate; + + neorv32_mtime_inst_false: + if (IO_MTIME_EN = false) generate + io_dev_rsp(IODEV_MTIME) <= rsp_terminate_c; + mtime_irq <= mtime_irq_i; + end generate; + + + -- Primary Universal Asynchronous Receiver/Transmitter (UART0) ---------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_uart0_inst_true: + if (IO_UART0_EN = true) generate + neorv32_uart0_inst: entity neorv32.neorv32_uart + generic map ( + UART_PRIMARY => true, + UART_RX_FIFO => IO_UART0_RX_FIFO, + UART_TX_FIFO => IO_UART0_TX_FIFO + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_UART0), + bus_rsp_o => io_dev_rsp(IODEV_UART0), + clkgen_en_o => cg_en.uart0, + clkgen_i => clk_gen, + uart_txd_o => uart0_txd_o, + uart_rxd_i => uart0_rxd_i, + uart_rts_o => uart0_rts_o, + uart_cts_i => uart0_cts_i, + irq_rx_o => firq.uart0_rx, + irq_tx_o => firq.uart0_tx + ); + end generate; + + neorv32_uart0_inst_false: + if (IO_UART0_EN = false) generate + io_dev_rsp(IODEV_UART0) <= rsp_terminate_c; + uart0_txd_o <= '0'; + uart0_rts_o <= '1'; + cg_en.uart0 <= '0'; + firq.uart0_rx <= '0'; + firq.uart0_tx <= '0'; + end generate; + + + -- Secondary Universal Asynchronous Receiver/Transmitter (UART1) -------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_uart1_inst_true: + if (IO_UART1_EN = true) generate + neorv32_uart1_inst: entity neorv32.neorv32_uart + generic map ( + UART_PRIMARY => false, + UART_RX_FIFO => IO_UART1_RX_FIFO, + UART_TX_FIFO => IO_UART1_TX_FIFO + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_UART1), + bus_rsp_o => io_dev_rsp(IODEV_UART1), + clkgen_en_o => cg_en.uart1, + clkgen_i => clk_gen, + uart_txd_o => uart1_txd_o, + uart_rxd_i => uart1_rxd_i, + uart_rts_o => uart1_rts_o, + uart_cts_i => uart1_cts_i, + irq_rx_o => firq.uart1_rx, + irq_tx_o => firq.uart1_tx + ); + end generate; + + neorv32_uart1_inst_false: + if (IO_UART1_EN = false) generate + io_dev_rsp(IODEV_UART1) <= rsp_terminate_c; + uart1_txd_o <= '0'; + uart1_rts_o <= '1'; + cg_en.uart1 <= '0'; + firq.uart1_rx <= '0'; + firq.uart1_tx <= '0'; + end generate; + + + -- Serial Peripheral Interface (SPI) ------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + neorv32_spi_inst_true: + if (IO_SPI_EN = true) generate + neorv32_spi_inst: entity neorv32.neorv32_spi + generic map ( + IO_SPI_FIFO => IO_SPI_FIFO + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_SPI), + bus_rsp_o => io_dev_rsp(IODEV_SPI), + clkgen_en_o => cg_en.spi, + clkgen_i => clk_gen, + spi_clk_o => spi_clk_o, + spi_dat_o => spi_dat_o, + spi_dat_i => spi_dat_i, + spi_csn_o => spi_csn_o, + irq_o => firq.spi + ); + end generate; + + neorv32_spi_inst_false: + if (IO_SPI_EN = false) generate + io_dev_rsp(IODEV_SPI) <= rsp_terminate_c; + spi_clk_o <= '0'; + spi_dat_o <= '0'; + spi_csn_o <= (others => '1'); + cg_en.spi <= '0'; + firq.spi <= '0'; + end generate; + + + -- Two-Wire Interface (TWI) --------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_twi_inst_true: + if (IO_TWI_EN = true) generate + neorv32_twi_inst: entity neorv32.neorv32_twi + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_TWI), + bus_rsp_o => io_dev_rsp(IODEV_TWI), + clkgen_en_o => cg_en.twi, + clkgen_i => clk_gen, + twi_sda_i => twi_sda_i, + twi_sda_o => twi_sda_o, + twi_scl_i => twi_scl_i, + twi_scl_o => twi_scl_o, + irq_o => firq.twi + ); + end generate; + + neorv32_twi_inst_false: + if (IO_TWI_EN = false) generate + io_dev_rsp(IODEV_TWI) <= rsp_terminate_c; + twi_sda_o <= '1'; + twi_scl_o <= '1'; + cg_en.twi <= '0'; + firq.twi <= '0'; + end generate; + + + -- Pulse-Width Modulation Controller (PWM) ------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + neorv32_pwm_inst_true: + if (IO_PWM_NUM_CH > 0) generate + neorv32_pwm_inst: entity neorv32.neorv32_pwm + generic map ( + NUM_CHANNELS => IO_PWM_NUM_CH + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_PWM), + bus_rsp_o => io_dev_rsp(IODEV_PWM), + clkgen_en_o => cg_en.pwm, + clkgen_i => clk_gen, + pwm_o => pwm_o + ); + end generate; + + neorv32_pwm_inst_false: + if (IO_PWM_NUM_CH = 0) generate + io_dev_rsp(IODEV_PWM) <= rsp_terminate_c; + cg_en.pwm <= '0'; + pwm_o <= (others => '0'); + end generate; + + + -- True Random Number Generator (TRNG) ---------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_trng_inst_true: + if (IO_TRNG_EN = true) generate + neorv32_trng_inst: entity neorv32.neorv32_trng + generic map ( + IO_TRNG_FIFO => IO_TRNG_FIFO + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_TRNG), + bus_rsp_o => io_dev_rsp(IODEV_TRNG), + irq_o => firq.trng + ); + end generate; + + neorv32_trng_inst_false: + if (IO_TRNG_EN = false) generate + io_dev_rsp(IODEV_TRNG) <= rsp_terminate_c; + firq.trng <= '0'; + end generate; + + + -- Smart LED (WS2811/WS2812) Interface (NEOLED) ------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_neoled_inst_true: + if (IO_NEOLED_EN = true) generate + neorv32_neoled_inst: entity neorv32.neorv32_neoled + generic map ( + FIFO_DEPTH => IO_NEOLED_TX_FIFO + ) + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_NEOLED), + bus_rsp_o => io_dev_rsp(IODEV_NEOLED), + clkgen_en_o => cg_en.neoled, + clkgen_i => clk_gen, + irq_o => firq.neoled, + neoled_o => neoled_o + ); + end generate; + + neorv32_neoled_inst_false: + if (IO_NEOLED_EN = false) generate + io_dev_rsp(IODEV_NEOLED) <= rsp_terminate_c; + cg_en.neoled <= '0'; + firq.neoled <= '0'; + neoled_o <= '0'; + end generate; + + + -- External Interrupt Controller (XIRQ) --------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_xirq_inst_true: + if (XIRQ_NUM_CH > 0) generate + neorv32_xirq_inst: entity neorv32.neorv32_xirq + generic map ( + XIRQ_NUM_CH => XIRQ_NUM_CH, + XIRQ_TRIGGER_TYPE => XIRQ_TRIGGER_TYPE, + XIRQ_TRIGGER_POLARITY => XIRQ_TRIGGER_POLARITY + ) + port map ( + -- host access -- + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_XIRQ), + bus_rsp_o => io_dev_rsp(IODEV_XIRQ), + xirq_i => xirq_i, + cpu_irq_o => firq.xirq + ); + end generate; + + neorv32_xirq_inst_false: + if (XIRQ_NUM_CH = 0) generate + io_dev_rsp(IODEV_XIRQ) <= rsp_terminate_c; + firq.xirq <= '0'; + end generate; + + + -- General Purpose Timer (GPTMR) ---------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_gptmr_inst_true: + if (IO_GPTMR_EN = true) generate + neorv32_gptmr_inst: entity neorv32.neorv32_gptmr + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_GPTMR), + bus_rsp_o => io_dev_rsp(IODEV_GPTMR), + clkgen_en_o => cg_en.gptmr, + clkgen_i => clk_gen, + irq_o => firq.gptmr + ); + end generate; + + neorv32_gptmr_inst_false: + if (IO_GPTMR_EN = false) generate + io_dev_rsp(IODEV_GPTMR) <= rsp_terminate_c; + cg_en.gptmr <= '0'; + firq.gptmr <= '0'; + end generate; + + + -- 1-Wire Interface Controller (ONEWIRE) -------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_onewire_inst_true: + if (IO_ONEWIRE_EN = true) generate + neorv32_onewire_inst: entity neorv32.neorv32_onewire + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_ONEWIRE), + bus_rsp_o => io_dev_rsp(IODEV_ONEWIRE), + clkgen_en_o => cg_en.onewire, + clkgen_i => clk_gen, + onewire_i => onewire_i, + onewire_o => onewire_o, + irq_o => firq.onewire + ); + end generate; + + neorv32_onewire_inst_false: + if (IO_ONEWIRE_EN = false) generate + io_dev_rsp(IODEV_ONEWIRE) <= rsp_terminate_c; + onewire_o <= '1'; + cg_en.onewire <= '0'; + firq.onewire <= '0'; + end generate; + + + -- Stream Link Interface (SLINK) ---------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_slink_inst_true: + if (IO_SLINK_EN = true) generate + neorv32_slink_inst: entity neorv32.neorv32_slink + generic map ( + SLINK_RX_FIFO => IO_SLINK_RX_FIFO, + SLINK_TX_FIFO => IO_SLINK_TX_FIFO + ) + port map ( + -- Host access -- + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_SLINK), + bus_rsp_o => io_dev_rsp(IODEV_SLINK), + irq_o => firq.slink, + -- RX stream interface -- + slink_rx_data_i => slink_rx_dat_i, + slink_rx_valid_i => slink_rx_val_i, + slink_rx_ready_o => slink_rx_rdy_o, + -- TX stream interface -- + slink_tx_data_o => slink_tx_dat_o, + slink_tx_valid_o => slink_tx_val_o, + slink_tx_ready_i => slink_tx_rdy_i + ); + end generate; + + neorv32_slink_inst_false: + if (IO_SLINK_EN = false) generate + io_dev_rsp(IODEV_SLINK) <= rsp_terminate_c; + firq.slink <= '0'; + slink_rx_rdy_o <= '0'; + slink_tx_dat_o <= (others => '0'); + slink_tx_val_o <= '0'; + end generate; + + + -- Cyclic Redundancy Check Unit (CRC) ----------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_crc_inst_true: + if (IO_CRC_EN = true) generate + neorv32_crc_inst: entity neorv32.neorv32_crc + port map ( + clk_i => clk_i, + rstn_i => rstn_int, + bus_req_i => io_dev_req(IODEV_CRC), + bus_rsp_o => io_dev_rsp(IODEV_CRC) + ); + end generate; + + neorv32_crc_inst_false: + if (IO_CRC_EN = false) generate + io_dev_rsp(IODEV_CRC) <= rsp_terminate_c; + end generate; + + + -- System Configuration Information Memory (SYSINFO) -------------------------------------- + -- ------------------------------------------------------------------------------------------- + neorv32_sysinfo_inst: entity neorv32.neorv32_sysinfo generic map ( - SLINK_RX_FIFO => IO_SLINK_RX_FIFO, - SLINK_TX_FIFO => IO_SLINK_TX_FIFO + -- General -- + CLOCK_FREQUENCY => CLOCK_FREQUENCY, + CUSTOM_ID => CUSTOM_ID, + INT_BOOTLOADER_EN => INT_BOOTLOADER_EN, + -- Physical memory protection (PMP) -- + 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, + -- Internal Data memory -- + MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, + MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, + -- Instruction cache -- + ICACHE_EN => ICACHE_EN, + ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, + ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, + ICACHE_ASSOCIATIVITY => ICACHE_ASSOCIATIVITY, + -- Data cache -- + DCACHE_EN => DCACHE_EN, + DCACHE_NUM_BLOCKS => DCACHE_NUM_BLOCKS, + DCACHE_BLOCK_SIZE => DCACHE_BLOCK_SIZE, + -- External memory interface -- + MEM_EXT_EN => MEM_EXT_EN, + MEM_EXT_BIG_ENDIAN => MEM_EXT_BIG_ENDIAN, + -- On-Chip Debugger -- + ON_CHIP_DEBUGGER_EN => ON_CHIP_DEBUGGER_EN, + -- Processor peripherals -- + IO_GPIO_NUM => IO_GPIO_NUM, + IO_MTIME_EN => IO_MTIME_EN, + IO_UART0_EN => IO_UART0_EN, + IO_UART1_EN => IO_UART1_EN, + IO_SPI_EN => IO_SPI_EN, + IO_SDI_EN => IO_SDI_EN, + IO_TWI_EN => IO_TWI_EN, + IO_PWM_NUM_CH => IO_PWM_NUM_CH, + IO_WDT_EN => IO_WDT_EN, + IO_TRNG_EN => IO_TRNG_EN, + IO_CFS_EN => IO_CFS_EN, + IO_NEOLED_EN => IO_NEOLED_EN, + IO_XIRQ_NUM_CH => XIRQ_NUM_CH, + IO_GPTMR_EN => IO_GPTMR_EN, + IO_XIP_EN => IO_XIP_EN, + IO_ONEWIRE_EN => IO_ONEWIRE_EN, + IO_DMA_EN => IO_DMA_EN, + IO_SLINK_EN => IO_SLINK_EN, + IO_CRC_EN => IO_CRC_EN ) port map ( - -- Host access -- - clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_SLINK), - irq_o => firq.slink, - -- RX stream interface -- - slink_rx_data_i => slink_rx_dat_i, - slink_rx_valid_i => slink_rx_val_i, - slink_rx_ready_o => slink_rx_rdy_o, - -- TX stream interface -- - slink_tx_data_o => slink_tx_dat_o, - slink_tx_valid_o => slink_tx_val_o, - slink_tx_ready_i => slink_tx_rdy_i - ); - end generate; - - neorv32_slink_inst_false: - if (IO_SLINK_EN = false) generate - rsp_bus(DEV_SLINK) <= rsp_terminate_c; - firq.slink <= '0'; - slink_rx_rdy_o <= '0'; - slink_tx_dat_o <= (others => '0'); - slink_tx_val_o <= '0'; - end generate; - - - -- Cyclic Redundancy Check Unit (CRC) ----------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_crc_inst_true: - if (IO_CRC_EN = true) generate - neorv32_crc_inst: entity neorv32.neorv32_crc - port map ( clk_i => clk_i, - rstn_i => rstn_int, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_CRC) + bus_req_i => io_dev_req(IODEV_SYSINFO), + bus_rsp_o => io_dev_rsp(IODEV_SYSINFO) ); - end generate; - neorv32_crc_inst_false: - if (IO_CRC_EN = false) generate - rsp_bus(DEV_CRC) <= rsp_terminate_c; - end generate; + end generate; -- /io_system - -- System Configuration Information Memory (SYSINFO) -------------------------------------- - -- ------------------------------------------------------------------------------------------- - neorv32_sysinfo_inst: entity neorv32.neorv32_sysinfo - generic map ( - -- General -- - CLOCK_FREQUENCY => CLOCK_FREQUENCY, - CUSTOM_ID => CUSTOM_ID, - INT_BOOTLOADER_EN => INT_BOOTLOADER_EN, - -- Physical memory protection (PMP) -- - 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, - -- Internal Data memory -- - MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, - MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, - -- Instruction cache -- - ICACHE_EN => ICACHE_EN, - ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, - ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, - ICACHE_ASSOCIATIVITY => ICACHE_ASSOCIATIVITY, - -- Data cache -- - DCACHE_EN => DCACHE_EN, - DCACHE_NUM_BLOCKS => DCACHE_NUM_BLOCKS, - DCACHE_BLOCK_SIZE => DCACHE_BLOCK_SIZE, - -- External memory interface -- - MEM_EXT_EN => MEM_EXT_EN, - MEM_EXT_BIG_ENDIAN => MEM_EXT_BIG_ENDIAN, - -- On-Chip Debugger -- - ON_CHIP_DEBUGGER_EN => ON_CHIP_DEBUGGER_EN, - -- Processor peripherals -- - IO_GPIO_NUM => IO_GPIO_NUM, - IO_MTIME_EN => IO_MTIME_EN, - IO_UART0_EN => IO_UART0_EN, - IO_UART1_EN => IO_UART1_EN, - IO_SPI_EN => IO_SPI_EN, - IO_SDI_EN => IO_SDI_EN, - IO_TWI_EN => IO_TWI_EN, - IO_PWM_NUM_CH => IO_PWM_NUM_CH, - IO_WDT_EN => IO_WDT_EN, - IO_TRNG_EN => IO_TRNG_EN, - IO_CFS_EN => IO_CFS_EN, - IO_NEOLED_EN => IO_NEOLED_EN, - IO_XIRQ_NUM_CH => XIRQ_NUM_CH, - IO_GPTMR_EN => IO_GPTMR_EN, - IO_XIP_EN => IO_XIP_EN, - IO_ONEWIRE_EN => IO_ONEWIRE_EN, - IO_DMA_EN => IO_DMA_EN, - IO_SLINK_EN => IO_SLINK_EN, - IO_CRC_EN => IO_CRC_EN - ) - port map ( - clk_i => clk_i, - bus_req_i => io_req, - bus_rsp_o => rsp_bus(DEV_SYSINFO) - ); - - --- **************************************************************************************************************************** --- On-Chip Debugger Complex --- **************************************************************************************************************************** - + -- ************************************************************************************************************************** + -- On-Chip Debugger Complex + -- ************************************************************************************************************************** neorv32_neorv32_ocd_inst_true: if (ON_CHIP_DEBUGGER_EN = true) generate @@ -1474,6 +1546,9 @@ begin -- On-Chip Debugger - Debug Module (DM) --------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_debug_dm_inst: entity neorv32.neorv32_debug_dm + generic map ( + CPU_BASE_ADDR => base_io_dm_c + ) port map ( -- global control -- clk_i => clk_i, @@ -1490,8 +1565,8 @@ begin dmi_rsp_data_o => dmi.rsp_data, dmi_rsp_op_o => dmi.rsp_op, -- CPU bus access -- - bus_req_i => soc_req, - bus_rsp_o => rsp_bus(DEV_OCD), + bus_req_i => io_dev_req(IODEV_OCD), + bus_rsp_o => io_dev_rsp(IODEV_OCD), -- CPU control -- cpu_ndmrstn_o => dci_ndmrstn, cpu_halt_req_o => dci_halt_req @@ -1501,10 +1576,10 @@ begin neorv32_debug_ocd_inst_false: if (ON_CHIP_DEBUGGER_EN = false) generate - rsp_bus(DEV_OCD) <= rsp_terminate_c; - jtag_tdo_o <= jtag_tdi_i; -- JTAG feed-through - dci_ndmrstn <= '1'; - dci_halt_req <= '0'; + io_dev_rsp(IODEV_OCD) <= rsp_terminate_c; + jtag_tdo_o <= jtag_tdi_i; -- JTAG feed-through + dci_ndmrstn <= '1'; + dci_halt_req <= '0'; end generate; diff --git a/rtl/core/neorv32_trng.vhd b/rtl/core/neorv32_trng.vhd index e92910cdc..0b430d479 100644 --- a/rtl/core/neorv32_trng.vhd +++ b/rtl/core/neorv32_trng.vhd @@ -85,15 +85,6 @@ architecture neorv32_trng_rtl of neorv32_trng is constant ctrl_en_c : natural := 30; -- r/w: TRNG enable constant ctrl_valid_c : natural := 31; -- r/-: Output data valid - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(trng_size_c); -- low address boundary bit - - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal wren : std_ulogic; -- full word write enable - signal rden : std_ulogic; -- read enable - -- Component: neoTRNG true random number generator -- component neoTRNG generic ( @@ -148,11 +139,6 @@ begin -- Write Access --------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = trng_base_c(hi_abb_c downto lo_abb_c)) else '0'; - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -164,7 +150,7 @@ begin irq_fifo_full <= '0'; elsif rising_edge(clk_i) then fifo_clr <= '0'; -- auto-clear - if (wren = '1') then + if (bus_req_i.we = '1') then enable <= bus_req_i.data(ctrl_en_c); fifo_clr <= bus_req_i.data(ctrl_fifo_clr_c); irq_fifo_nempty <= bus_req_i.data(ctrl_irq_fifo_nempty); @@ -178,9 +164,9 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= wren or rden; -- host bus acknowledge + bus_rsp_o.ack <= bus_req_i.we or bus_req_i.re; -- host bus acknowledge bus_rsp_o.data <= (others => '0'); - if (rden = '1') then + if (bus_req_i.re = '1') then bus_rsp_o.data(ctrl_data_msb_c downto ctrl_data_lsb_c) <= fifo.rdata; -- bus_rsp_o.data(ctrl_fifo_size3_c downto ctrl_fifo_size0_c) <= std_ulogic_vector(to_unsigned(index_size_f(IO_TRNG_FIFO), 4)); @@ -245,7 +231,7 @@ begin ); fifo.clear <= '1' when (enable = '0') or (fifo_clr = '1') else '0'; - fifo.re <= '1' when (rden = '1') else '0'; + fifo.re <= '1' when (bus_req_i.re = '1') else '0'; -- FIFO-level interrupt generator -- irq_generator: process(clk_i) diff --git a/rtl/core/neorv32_twi.vhd b/rtl/core/neorv32_twi.vhd index c9ec14abc..a57c3e00b 100644 --- a/rtl/core/neorv32_twi.vhd +++ b/rtl/core/neorv32_twi.vhd @@ -62,10 +62,6 @@ end neorv32_twi; architecture neorv32_twi_rtl of neorv32_twi is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(twi_size_c); -- low address boundary bit - -- control register -- constant ctrl_en_c : natural := 0; -- r/w: TWI enable constant ctrl_start_c : natural := 1; -- -/w: Generate START condition @@ -84,12 +80,6 @@ architecture neorv32_twi_rtl of neorv32_twi is constant ctrl_ack_c : natural := 30; -- r/-: Set if ACK received constant ctrl_busy_c : natural := 31; -- r/-: Set if TWI unit is busy - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- control register -- type ctrl_t is record enable : std_ulogic; @@ -138,11 +128,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = twi_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= twi_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; -- write access -- write_access: process(rstn_i, clk_i) @@ -154,8 +139,8 @@ begin ctrl.prsc <= (others => '0'); ctrl.cdiv <= (others => '0'); elsif rising_edge(clk_i) then - if (wren = '1') then - if (addr = twi_ctrl_addr_c) then + if (bus_req_i.we = '1') then + if (bus_req_i.addr(2) = '0') then ctrl.enable <= bus_req_i.data(ctrl_en_c); ctrl.mack <= bus_req_i.data(ctrl_mack_c); ctrl.csen <= bus_req_i.data(ctrl_csen_c); @@ -170,10 +155,10 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; -- bus handshake + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- bus handshake bus_rsp_o.data <= (others => '0'); - if (rden = '1') then - if (addr = twi_ctrl_addr_c) then + if (bus_req_i.re = '1') then + if (bus_req_i.addr(2) = '0') then bus_rsp_o.data(ctrl_en_c) <= ctrl.enable; bus_rsp_o.data(ctrl_mack_c) <= ctrl.mack; bus_rsp_o.data(ctrl_csen_c) <= ctrl.csen; @@ -183,7 +168,7 @@ begin bus_rsp_o.data(ctrl_claimed_c) <= arbiter.claimed; bus_rsp_o.data(ctrl_ack_c) <= not arbiter.rtx_sreg(0); bus_rsp_o.data(ctrl_busy_c) <= arbiter.busy; - else -- twi_rtx_addr_c => + else bus_rsp_o.data(7 downto 0) <= arbiter.rtx_sreg(8 downto 1); end if; end if; @@ -268,14 +253,14 @@ begin when "100" => -- IDLE: waiting for operation requests -- ------------------------------------------------------------ arbiter.bitcnt <= (others => '0'); - if (wren = '1') then - if (addr = twi_ctrl_addr_c) then + if (bus_req_i.we = '1') then + if (bus_req_i.addr(2) = '0') then if (bus_req_i.data(ctrl_start_c) = '1') then -- issue START condition arbiter.state_nxt <= "01"; elsif (bus_req_i.data(ctrl_stop_c) = '1') then -- issue STOP condition arbiter.state_nxt <= "10"; end if; - elsif (addr = twi_rtx_addr_c) then -- start a data transmission + elsif (bus_req_i.addr(2) = '1') then -- start a data transmission -- one bit extra for ACK: issued by controller if ctrl_mack_c is set, -- sampled from peripheral if ctrl_mack_c is cleared arbiter.rtx_sreg <= bus_req_i.data(7 downto 0) & (not ctrl.mack); diff --git a/rtl/core/neorv32_uart.vhd b/rtl/core/neorv32_uart.vhd index 95f865ef8..09459b3d5 100644 --- a/rtl/core/neorv32_uart.vhd +++ b/rtl/core/neorv32_uart.vhd @@ -89,16 +89,6 @@ end neorv32_uart; architecture neorv32_uart_rtl of neorv32_uart is - -- interface configuration for UART0 / UART1 -- - constant uart_id_base_c : std_ulogic_vector(31 downto 0) := cond_sel_stdulogicvector_f(UART_PRIMARY, uart0_base_c, uart1_base_c); - constant uart_id_size_c : natural := cond_sel_natural_f( UART_PRIMARY, uart0_size_c, uart1_size_c); - constant uart_id_ctrl_addr_c : std_ulogic_vector(31 downto 0) := cond_sel_stdulogicvector_f(UART_PRIMARY, uart0_ctrl_addr_c, uart1_ctrl_addr_c); - constant uart_id_rtx_addr_c : std_ulogic_vector(31 downto 0) := cond_sel_stdulogicvector_f(UART_PRIMARY, uart0_rtx_addr_c, uart1_rtx_addr_c); - - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(uart_id_size_c); -- low address boundary bit - -- simulation output configuration -- constant sim_screen_output_en_c : boolean := true; -- output lowest byte as char to simulator console when enabled constant sim_text_output_en_c : boolean := true; -- output lowest byte as char to text file when enabled @@ -147,12 +137,6 @@ architecture neorv32_uart_rtl of neorv32_uart is constant data_tx_fifo_size_lsb : natural := 12; -- r/-: log2(TX fifo size) LSB constant data_tx_fifo_size_msb : natural := 15; -- r/-: log2(TX fifo size) MSB - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- clock generator -- signal uart_clk : std_ulogic; @@ -221,12 +205,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = uart_id_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= uart_id_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; - -- write access -- write_access: process(rstn_i, clk_i) begin @@ -242,8 +220,8 @@ begin ctrl.irq_tx_empty <= '0'; ctrl.irq_tx_nhalf <= '0'; elsif rising_edge(clk_i) then - if (wren = '1') then - if (addr = uart_id_ctrl_addr_c) then -- control register + if (bus_req_i.we = '1') then + if (bus_req_i.addr(2) = '0') then -- control register ctrl.enable <= bus_req_i.data(ctrl_en_c); ctrl.sim_mode <= bus_req_i.data(ctrl_sim_en_c); ctrl.hwfc_en <= bus_req_i.data(ctrl_hwfc_en_c); @@ -264,10 +242,10 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= wren or rden; -- bus access acknowledge + bus_rsp_o.ack <= bus_req_i.we or bus_req_i.re; -- bus access acknowledge bus_rsp_o.data <= (others => '0'); - if (rden = '1') then - if (addr = uart_id_ctrl_addr_c) then -- control register + if (bus_req_i.re = '1') then + if (bus_req_i.addr(2) = '0') then -- control register bus_rsp_o.data(ctrl_en_c) <= ctrl.enable; bus_rsp_o.data(ctrl_sim_en_c) <= ctrl.sim_mode; bus_rsp_o.data(ctrl_hwfc_en_c) <= ctrl.hwfc_en; @@ -335,7 +313,7 @@ begin tx_fifo.clear <= '1' when (ctrl.enable = '0') or (ctrl.sim_mode = '1') else '0'; tx_fifo.wdata <= bus_req_i.data(data_rtx_msb_c downto data_rtx_lsb_c); - tx_fifo.we <= '1' when (wren = '1') and (addr = uart_id_rtx_addr_c) else '0'; + tx_fifo.we <= '1' when (bus_req_i.we = '1') and (bus_req_i.addr(2) = '1') else '0'; tx_fifo.re <= '1' when (tx_engine.state = "100") else '0'; -- TX interrupt generator -- @@ -376,7 +354,7 @@ begin rx_fifo.clear <= '1' when (ctrl.enable = '0') or (ctrl.sim_mode = '1') else '0'; rx_fifo.wdata <= rx_engine.sreg(8 downto 1); rx_fifo.we <= rx_engine.done; - rx_fifo.re <= '1' when (rden = '1') and (addr = uart_id_rtx_addr_c) else '0'; + rx_fifo.re <= '1' when (bus_req_i.re = '1') and (bus_req_i.addr(2) = '1') else '0'; -- RX interrupt generator -- rx_irq_generator: process(clk_i) @@ -506,7 +484,7 @@ begin fifo_overrun: process(clk_i) begin if rising_edge(clk_i) then - if ((rden = '1') and (addr = uart_id_rtx_addr_c)) or (ctrl.enable = '0') then -- clear when reading data register + if ((bus_req_i.re = '1') and (bus_req_i.addr(2) = '1')) or (ctrl.enable = '0') then -- clear when reading data register rx_engine.over <= '0'; elsif (rx_fifo.we = '1') and (rx_fifo.free = '0') then -- writing to full FIFO rx_engine.over <= '1'; @@ -546,7 +524,7 @@ begin begin if rising_edge(clk_i) then if (ctrl.enable = '1') and (ctrl.sim_mode = '1') and -- UART simulation mode - (wren = '1') and (addr = uart_id_rtx_addr_c) then + (bus_req_i.we = '1') and (bus_req_i.addr(2) = '1') then -- print lowest byte as ASCII char -- char_v := to_integer(unsigned(bus_req_i.data(7 downto 0))); diff --git a/rtl/core/neorv32_wdt.vhd b/rtl/core/neorv32_wdt.vhd index c1357a3cf..dc9b89811 100644 --- a/rtl/core/neorv32_wdt.vhd +++ b/rtl/core/neorv32_wdt.vhd @@ -65,10 +65,6 @@ end neorv32_wdt; architecture neorv32_wdt_rtl of neorv32_wdt is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(wdt_size_c); -- low address boundary bit - -- Control register bits -- constant ctrl_enable_c : natural := 0; -- r/w: WDT enable constant ctrl_lock_c : natural := 1; -- r/w: lock write access to control register when set @@ -80,11 +76,6 @@ architecture neorv32_wdt_rtl of neorv32_wdt is constant ctrl_timeout_lsb_c : natural := 8; -- r/w: timeout value LSB constant ctrl_timeout_msb_c : natural := 31; -- r/w: timeout value MSB - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal wren : std_ulogic; - signal rden : std_ulogic; - -- control register -- type ctrl_t is record enable : std_ulogic; -- WDT enable @@ -114,10 +105,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = wdt_base_c(hi_abb_c downto lo_abb_c)) else '0'; - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; -- write access -- write_access: process(rstn_int_i, clk_i) @@ -131,7 +118,7 @@ begin ctrl.timeout <= (others => '0'); elsif rising_edge(clk_i) then ctrl.reset <= '0'; -- default - if (wren = '1') then + if (bus_req_i.we = '1') then ctrl.reset <= bus_req_i.data(ctrl_reset_c); if (ctrl.lock = '0') then -- update configuration only if not locked ctrl.enable <= bus_req_i.data(ctrl_enable_c); @@ -148,9 +135,9 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; bus_rsp_o.data <= (others => '0'); - if (rden = '1') then + if (bus_req_i.re = '1') then bus_rsp_o.data(ctrl_enable_c) <= ctrl.enable; bus_rsp_o.data(ctrl_lock_c) <= ctrl.lock; bus_rsp_o.data(ctrl_dben_c) <= ctrl.dben; diff --git a/rtl/core/neorv32_wishbone.vhd b/rtl/core/neorv32_wishbone.vhd index 39bc5a341..a4bdf54e3 100644 --- a/rtl/core/neorv32_wishbone.vhd +++ b/rtl/core/neorv32_wishbone.vhd @@ -1,11 +1,8 @@ -- ################################################################################################# -- # << NEORV32 - External Bus Interface (WISHBONE) >> # -- # ********************************************************************************************* # --- # All bus accesses from the CPU, which do not target the internal IO region / the internal # --- # bootloader / the OCD system / the internal instruction or data memories (if implemented), are # --- # delegated via this Wishbone gateway to the external bus interface. Wishbone accesses can have # --- # a response latency of up to BUS_TIMEOUT - 1 cycles or an infinity response time if # --- # BUS_TIMEOUT = 0 (not recommended!) # +-- # Wishbone accesses can have a response latency of up to BUS_TIMEOUT - 1 cycles or an infinite # +-- # response time if BUS_TIMEOUT = 0 (not recommended!). # -- # # -- # The Wishbone gateway registers all outgoing signals. These signals will remain stable (gated) # -- # if there is no active Wishbone access. By default, also the incoming signals are registered, # @@ -51,39 +48,29 @@ use neorv32.neorv32_package.all; entity neorv32_wishbone is generic ( - -- Internal instruction memory -- - MEM_INT_IMEM_EN : boolean; -- implement processor-internal instruction memory - MEM_INT_IMEM_SIZE : natural; -- size of processor-internal instruction memory in bytes - -- Internal data memory -- - MEM_INT_DMEM_EN : boolean; -- implement processor-internal data memory - MEM_INT_DMEM_SIZE : natural; -- size of processor-internal data memory in bytes - -- Interface Configuration -- - BUS_TIMEOUT : natural; -- cycles after an UNACKNOWLEDGED bus access triggers a bus fault exception - PIPE_MODE : boolean; -- protocol: false=classic/standard wishbone mode, true=pipelined wishbone mode - BIG_ENDIAN : boolean; -- byte order: true=big-endian, false=little-endian - ASYNC_RX : boolean; -- use register buffer for RX data when false - ASYNC_TX : boolean -- use register buffer for TX data when false + -- Wishbone Interface Configuration -- + BUS_TIMEOUT : natural; -- cycles after an UNACKNOWLEDGED bus access triggers a bus fault exception + PIPE_MODE : boolean; -- protocol: false=classic/standard wishbone mode, true=pipelined wishbone mode + BIG_ENDIAN : boolean; -- byte order: true=big-endian, false=little-endian + ASYNC_RX : boolean; -- use register buffer for RX data when false + ASYNC_TX : boolean -- use register buffer for TX data when false ); port ( - clk_i : in std_ulogic; -- global clock line - rstn_i : in std_ulogic; -- global reset line, low-active - bus_req_i : in bus_req_t; -- bus request - bus_rsp_o : out bus_rsp_t; -- bus response - tmo_o : out std_ulogic; -- transfer timeout - ext_o : out std_ulogic; -- active external access - xip_en_i : in std_ulogic; -- XIP module enabled - xip_page_i : in std_ulogic_vector(03 downto 0); -- XIP memory page + clk_i : in std_ulogic; -- global clock line + rstn_i : in std_ulogic; -- global reset line, low-active + bus_req_i : in bus_req_t; -- bus request + bus_rsp_o : out bus_rsp_t; -- bus response -- - wb_tag_o : out std_ulogic_vector(02 downto 0); -- request tag - wb_adr_o : out std_ulogic_vector(31 downto 0); -- address - wb_dat_i : in std_ulogic_vector(31 downto 0); -- read data - wb_dat_o : out std_ulogic_vector(31 downto 0); -- write data - wb_we_o : out std_ulogic; -- read/write - wb_sel_o : out std_ulogic_vector(03 downto 0); -- byte enable - wb_stb_o : out std_ulogic; -- strobe - wb_cyc_o : out std_ulogic; -- valid cycle - wb_ack_i : in std_ulogic; -- transfer acknowledge - wb_err_i : in std_ulogic -- transfer error + wb_tag_o : out std_ulogic_vector(02 downto 0); -- request tag + wb_adr_o : out std_ulogic_vector(31 downto 0); -- address + wb_dat_i : in std_ulogic_vector(31 downto 0); -- read data + wb_dat_o : out std_ulogic_vector(31 downto 0); -- write data + wb_we_o : out std_ulogic; -- read/write + wb_sel_o : out std_ulogic_vector(03 downto 0); -- byte enable + wb_stb_o : out std_ulogic; -- strobe + wb_cyc_o : out std_ulogic; -- valid cycle + wb_ack_i : in std_ulogic; -- transfer acknowledge + wb_err_i : in std_ulogic -- transfer error ); end neorv32_wishbone; @@ -92,13 +79,6 @@ architecture neorv32_wishbone_rtl of neorv32_wishbone is -- timeout enable -- constant timeout_en_c : boolean := boolean(BUS_TIMEOUT /= 0); -- timeout enabled if BUS_TIMEOUT > 0 - -- access control -- - signal int_imem_acc : std_ulogic; - signal int_dmem_acc : std_ulogic; - signal int_btio_acc : std_ulogic; - signal xip_acc : std_ulogic; - signal xbus_access : std_ulogic; - -- bus arbiter type ctrl_t is record state : std_ulogic; @@ -110,7 +90,6 @@ architecture neorv32_wishbone_rtl of neorv32_wishbone is sel : std_ulogic_vector(03 downto 0); ack : std_ulogic; err : std_ulogic; - tmo : std_ulogic; timeout : std_ulogic_vector(index_size_f(BUS_TIMEOUT) downto 0); src : std_ulogic; priv : std_ulogic; @@ -126,6 +105,7 @@ architecture neorv32_wishbone_rtl of neorv32_wishbone is -- async RX gating -- signal ack_gated : std_ulogic; + signal err_gated : std_ulogic; signal rdata_gated : std_ulogic_vector(31 downto 0); begin @@ -142,21 +122,8 @@ begin severity note; -- zero timeout warning -- - assert not (BUS_TIMEOUT = 0) - report "NEORV32 PROCESSOR CONFIG WARNING! Ext. Bus Interface - NO auto-timeout defined; can cause permanent CPU stall!" severity warning; - - - -- Access Control ------------------------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - -- access to processor-internal IMEM or DMEM? -- - int_imem_acc <= '1' when (bus_req_i.addr(31 downto index_size_f(MEM_INT_IMEM_SIZE)) = imem_base_c(31 downto index_size_f(MEM_INT_IMEM_SIZE))) and (MEM_INT_IMEM_EN = true) else '0'; - int_dmem_acc <= '1' when (bus_req_i.addr(31 downto index_size_f(MEM_INT_DMEM_SIZE)) = dmem_base_c(31 downto index_size_f(MEM_INT_DMEM_SIZE))) and (MEM_INT_DMEM_EN = true) else '0'; - -- access to processor-internal BOOTROM or IO/peripheral devices? -- - int_btio_acc <= '1' when (bus_req_i.addr(31 downto 16) = boot_rom_base_c(31 downto 16)) else '0'; - -- XIP access? -- - xip_acc <= '1' when (xip_en_i = '1') and (bus_req_i.addr(31 downto 28) = xip_page_i) else '0'; - -- actual external bus access? -- - xbus_access <= (not int_imem_acc) and (not int_dmem_acc) and (not int_btio_acc) and (not xip_acc); + assert not (BUS_TIMEOUT = 0) report + "NEORV32 PROCESSOR CONFIG WARNING! Ext. Bus Interface - NO auto-timeout defined; can cause permanent CPU stall!" severity warning; -- Bus Arbiter ----------------------------------------------------------------------------- @@ -174,7 +141,6 @@ begin ctrl.timeout <= (others => '0'); ctrl.ack <= '0'; ctrl.err <= '0'; - ctrl.tmo <= '0'; ctrl.src <= '0'; ctrl.priv <= '0'; elsif rising_edge(clk_i) then @@ -183,13 +149,12 @@ begin ctrl.rdat <= (others => '0'); -- required for internal output gating ctrl.ack <= '0'; ctrl.err <= '0'; - ctrl.tmo <= '0'; ctrl.timeout <= std_ulogic_vector(to_unsigned(BUS_TIMEOUT, index_size_f(BUS_TIMEOUT)+1)); -- state machine -- if (ctrl.state = '0') then -- IDLE, waiting for host request -- ------------------------------------------------------------ - if (xbus_access = '1') and ((bus_req_i.we or bus_req_i.re) = '1') then -- valid external request + if (bus_req_i.we = '1') or (bus_req_i.re = '1') then -- request -- buffer (and gate) all outgoing signals -- ctrl.we <= bus_req_i.we; ctrl.adr <= bus_req_i.addr; @@ -203,15 +168,12 @@ begin else -- BUSY, transfer in progress -- ------------------------------------------------------------ ctrl.rdat <= wb_dat_i; - if (wb_err_i = '1') then -- abnormal bus termination - ctrl.err <= '1'; - ctrl.state <= '0'; - elsif (timeout_en_c = true) and (or_reduce_f(ctrl.timeout) = '0') then -- enabled timeout - ctrl.tmo <= '1'; - ctrl.state <= '0'; - elsif (wb_ack_i = '1') then -- normal bus termination + if (wb_ack_i = '1') then -- normal bus termination ctrl.ack <= '1'; ctrl.state <= '0'; + elsif (wb_err_i = '1') or ((timeout_en_c = true) and (or_reduce_f(ctrl.timeout) = '0')) then -- bus error or timeout + ctrl.err <= '1'; + ctrl.state <= '0'; end if; -- timeout counter -- if (timeout_en_c = true) then @@ -221,31 +183,27 @@ begin end if; end process bus_arbiter; - -- active external access -- - ext_o <= ctrl.state; - -- endianness conversion -- end_wdata <= bswap32_f(bus_req_i.data) when (BIG_ENDIAN = true) else bus_req_i.data; end_byteen <= bit_rev_f(bus_req_i.ben) when (BIG_ENDIAN = true) else bus_req_i.ben; - -- host access -- ack_gated <= wb_ack_i when (ctrl.state = '1') else '0'; -- CPU ACK gate for "async" RX + err_gated <= wb_err_i when (ctrl.state = '1') else '0'; -- CPU ERR gate for "async" RX rdata_gated <= wb_dat_i when (ctrl.state = '1') else (others => '0'); -- CPU read data gate for "async" RX - rdata <= ctrl.rdat when (ASYNC_RX = false) else rdata_gated; + rdata <= ctrl.rdat when (ASYNC_RX = false) else rdata_gated; bus_rsp_o.data <= rdata when (BIG_ENDIAN = false) else bswap32_f(rdata); -- endianness conversion bus_rsp_o.ack <= ctrl.ack when (ASYNC_RX = false) else ack_gated; - bus_rsp_o.err <= ctrl.err; - tmo_o <= ctrl.tmo; + bus_rsp_o.err <= ctrl.err when (ASYNC_RX = false) else err_gated; -- wishbone interface -- wb_tag_o(0) <= bus_req_i.priv when (ASYNC_TX = true) else ctrl.priv; -- 0 = unprivileged (U-mode), 1 = privileged (M-mode) wb_tag_o(1) <= '0'; -- 0 = secure, 1 = non-secure wb_tag_o(2) <= bus_req_i.src when (ASYNC_TX = true) else ctrl.src; -- 0 = data access, 1 = instruction access - stb_int <= (xbus_access and (bus_req_i.we or bus_req_i.re)) when (ASYNC_TX = true) else (ctrl.state and (not ctrl.state_ff)); - cyc_int <= ((xbus_access and (bus_req_i.we or bus_req_i.re)) or ctrl.state) when (ASYNC_TX = true) else ctrl.state; + stb_int <= (bus_req_i.we or bus_req_i.re) when (ASYNC_TX = true) else (ctrl.state and (not ctrl.state_ff)); + cyc_int <= ((bus_req_i.we or bus_req_i.re) or ctrl.state) when (ASYNC_TX = true) else ctrl.state; wb_adr_o <= bus_req_i.addr when (ASYNC_TX = true) else ctrl.adr; wb_dat_o <= bus_req_i.data when (ASYNC_TX = true) else ctrl.wdat; diff --git a/rtl/core/neorv32_xip.vhd b/rtl/core/neorv32_xip.vhd index addf24c83..9c6170008 100644 --- a/rtl/core/neorv32_xip.vhd +++ b/rtl/core/neorv32_xip.vhd @@ -53,9 +53,6 @@ entity neorv32_xip is bus_rsp_o : out bus_rsp_t; -- bus response xip_req_i : in bus_req_t; -- XIP request xip_rsp_o : out bus_rsp_t; -- XIP response - xip_en_o : out std_ulogic; -- XIP enable - xip_acc_o : out std_ulogic; -- pending XIP access - xip_page_o : out std_ulogic_vector(3 downto 0); -- XIP page clkgen_en_o : out std_ulogic; -- enable clock generator clkgen_i : in std_ulogic_vector(7 downto 0); spi_csn_o : out std_ulogic; -- chip-select, low-active @@ -67,16 +64,6 @@ end neorv32_xip; architecture neorv32_xip_rtl of neorv32_xip is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(xip_size_c); -- low address boundary bit - - -- CT register access control -- - signal ct_acc_en : std_ulogic; -- module access enable - signal ct_addr : std_ulogic_vector(31 downto 0); -- access address - signal ct_wren : std_ulogic; -- word write enable - signal ct_rden : std_ulogic; -- read enable - -- control register -- constant ctrl_enable_c : natural := 0; -- r/w: module enable constant ctrl_spi_prsc0_c : natural := 1; -- r/w: SPI clock prescaler select - bit 0 @@ -91,16 +78,14 @@ architecture neorv32_xip_rtl of neorv32_xip is constant ctrl_xip_abytes1_c : natural := 12; -- r/w: XIP number of address bytes (0=1,1=2,2=3,3=4) - bit 1 constant ctrl_rd_cmd0_c : natural := 13; -- r/w: SPI flash read command - bit 0 constant ctrl_rd_cmd7_c : natural := 20; -- r/w: SPI flash read command - bit 7 - constant ctrl_page0_c : natural := 21; -- r/w: XIP memory page - bit 0 - constant ctrl_page3_c : natural := 24; -- r/w: XIP memory page - bit 3 - constant ctrl_spi_csen_c : natural := 25; -- r/w: SPI chip-select enabled - constant ctrl_highspeed_c : natural := 26; -- r/w: SPI high-speed mode enable (ignoring ctrl_spi_prsc) - constant ctrl_burst_en_c : natural := 27; -- r/w: XIP burst mode enable + constant ctrl_spi_csen_c : natural := 21; -- r/w: SPI chip-select enabled + constant ctrl_highspeed_c : natural := 22; -- r/w: SPI high-speed mode enable (ignoring ctrl_spi_prsc) + constant ctrl_burst_en_c : natural := 23; -- r/w: XIP burst mode enable -- constant ctrl_phy_busy_c : natural := 30; -- r/-: SPI PHY is busy when set constant ctrl_xip_busy_c : natural := 31; -- r/-: XIP access in progress -- - signal ctrl : std_ulogic_vector(27 downto 0); + signal ctrl : std_ulogic_vector(23 downto 0); -- Direct SPI access registers -- signal spi_data_lo : std_ulogic_vector(31 downto 0); @@ -117,6 +102,7 @@ architecture neorv32_xip_rtl of neorv32_xip is state_nxt : arbiter_state_t; addr : std_ulogic_vector(31 downto 0); addr_lookahead : std_ulogic_vector(31 downto 0); + xip_acc_err : std_ulogic; busy : std_ulogic; tmo_cnt : std_ulogic_vector(04 downto 0); -- timeout counter for auto CS de-assert (burst mode only) end record; @@ -163,14 +149,6 @@ architecture neorv32_xip_rtl of neorv32_xip is begin - -- Access Control (IO/CTRL port) ---------------------------------------------------------- - -- ------------------------------------------------------------------------------------------- - ct_acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = xip_base_c(hi_abb_c downto lo_abb_c)) else '0'; - ct_addr <= xip_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - ct_wren <= ct_acc_en and bus_req_i.we; - ct_rden <= ct_acc_en and bus_req_i.re; - - -- Control Write Access ------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- ctrl_write_access : process(rstn_i, clk_i) @@ -182,9 +160,9 @@ begin spi_trigger <= '0'; elsif rising_edge(clk_i) then spi_trigger <= '0'; - if (ct_wren = '1') then -- only full-word writes! + if (bus_req_i.we = '1') then -- only full-word writes! -- control register -- - if (ct_addr = xip_ctrl_addr_c) then + if (bus_req_i.addr(3 downto 2) = "00") then ctrl(ctrl_enable_c) <= bus_req_i.data(ctrl_enable_c); ctrl(ctrl_spi_prsc2_c downto ctrl_spi_prsc0_c) <= bus_req_i.data(ctrl_spi_prsc2_c downto ctrl_spi_prsc0_c); ctrl(ctrl_spi_cpol_c) <= bus_req_i.data(ctrl_spi_cpol_c); @@ -193,17 +171,16 @@ begin ctrl(ctrl_xip_enable_c) <= bus_req_i.data(ctrl_xip_enable_c); ctrl(ctrl_xip_abytes1_c downto ctrl_xip_abytes0_c) <= bus_req_i.data(ctrl_xip_abytes1_c downto ctrl_xip_abytes0_c); ctrl(ctrl_rd_cmd7_c downto ctrl_rd_cmd0_c) <= bus_req_i.data(ctrl_rd_cmd7_c downto ctrl_rd_cmd0_c); - ctrl(ctrl_page3_c downto ctrl_page0_c) <= bus_req_i.data(ctrl_page3_c downto ctrl_page0_c); ctrl(ctrl_spi_csen_c) <= bus_req_i.data(ctrl_spi_csen_c); ctrl(ctrl_highspeed_c) <= bus_req_i.data(ctrl_highspeed_c); ctrl(ctrl_burst_en_c) <= bus_req_i.data(ctrl_burst_en_c); end if; -- SPI direct data access register lo -- - if (ct_addr = xip_data_lo_addr_c) then + if (bus_req_i.addr(3 downto 2) = "10") then spi_data_lo <= bus_req_i.data; end if; -- SPI direct data access register hi -- - if (ct_addr = xip_data_hi_addr_c) then + if (bus_req_i.addr(3 downto 2) = "11") then spi_data_hi <= bus_req_i.data; spi_trigger <= '1'; -- trigger direct SPI transaction end if; @@ -211,22 +188,16 @@ begin end if; end process ctrl_write_access; - -- XIP enabled -- - xip_en_o <= ctrl(ctrl_enable_c); - - -- XIP page output -- - xip_page_o <= ctrl(ctrl_page3_c downto ctrl_page0_c); - -- Control Read Access -------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- ctrl_read_access : process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= ct_wren or ct_rden; -- access acknowledge + bus_rsp_o.ack <= bus_req_i.we or bus_req_i.re; -- access acknowledge bus_rsp_o.data <= (others => '0'); - if (ct_rden = '1') then - case ct_addr(3 downto 2) is + if (bus_req_i.re = '1') then + case bus_req_i.addr(3 downto 2) is when "00" => -- 'xip_ctrl_addr_c' - control register bus_rsp_o.data(ctrl_enable_c) <= ctrl(ctrl_enable_c); bus_rsp_o.data(ctrl_spi_prsc2_c downto ctrl_spi_prsc0_c) <= ctrl(ctrl_spi_prsc2_c downto ctrl_spi_prsc0_c); @@ -236,7 +207,6 @@ begin bus_rsp_o.data(ctrl_xip_enable_c) <= ctrl(ctrl_xip_enable_c); bus_rsp_o.data(ctrl_xip_abytes1_c downto ctrl_xip_abytes0_c) <= ctrl(ctrl_xip_abytes1_c downto ctrl_xip_abytes0_c); bus_rsp_o.data(ctrl_rd_cmd7_c downto ctrl_rd_cmd0_c) <= ctrl(ctrl_rd_cmd7_c downto ctrl_rd_cmd0_c); - bus_rsp_o.data(ctrl_page3_c downto ctrl_page0_c) <= ctrl(ctrl_page3_c downto ctrl_page0_c); bus_rsp_o.data(ctrl_spi_csen_c) <= ctrl(ctrl_spi_csen_c); bus_rsp_o.data(ctrl_highspeed_c) <= ctrl(ctrl_highspeed_c); bus_rsp_o.data(ctrl_burst_en_c) <= ctrl(ctrl_burst_en_c); @@ -285,10 +255,16 @@ begin arbiter.state <= arbiter.state_nxt; end if; -- address look-ahead -- - if (xip_req_i.re = '1') and (xip_req_i.addr(31 downto 28) = ctrl(ctrl_page3_c downto ctrl_page0_c)) then + if (xip_req_i.re = '1') then arbiter.addr <= xip_req_i.addr; -- buffer address (reducing fan-out on CPU's address net) end if; arbiter.addr_lookahead <= std_ulogic_vector(unsigned(arbiter.addr) + 4); -- prefetch address of *next* linear access + -- XIP access error? -- + if (arbiter.state = S_DIRECT) then + arbiter.xip_acc_err <= xip_req_i.re or xip_req_i.we; + else + arbiter.xip_acc_err <= '0'; + end if; -- pending flash access timeout -- if (ctrl(ctrl_enable_c) = '0') or (ctrl(ctrl_xip_enable_c) = '0') or (arbiter.state = S_BUSY) then -- sync reset arbiter.tmo_cnt <= (others => '0'); @@ -308,7 +284,7 @@ begin -- bus interface defaults -- xip_rsp_o.data <= (others => '0'); xip_rsp_o.ack <= '0'; - xip_rsp_o.err <= '0'; + xip_rsp_o.err <= arbiter.xip_acc_err; -- SPI PHY interface defaults -- phy_if.start <= '0'; @@ -327,12 +303,10 @@ begin when S_IDLE => -- wait for new bus request -- ------------------------------------------------------------ - if (xip_req_i.addr(31 downto 28) = ctrl(ctrl_page3_c downto ctrl_page0_c)) then - if (xip_req_i.re = '1') then - arbiter.state_nxt <= S_CHECK; - elsif (xip_req_i.we = '1') then - arbiter.state_nxt <= S_ERROR; - end if; + if (xip_req_i.re = '1') then + arbiter.state_nxt <= S_CHECK; + elsif (xip_req_i.we = '1') then + arbiter.state_nxt <= S_ERROR; end if; when S_CHECK => -- check if we can resume flash access @@ -374,9 +348,6 @@ begin -- arbiter status -- arbiter.busy <= '1' when (arbiter.state = S_TRIG) or (arbiter.state = S_BUSY) else '0'; -- actual XIP access in progress - -- status output -- - xip_acc_o <= arbiter.busy; - -- SPI Clock Generator -------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- diff --git a/rtl/core/neorv32_xirq.vhd b/rtl/core/neorv32_xirq.vhd index 4d2846ecc..b1bde603d 100644 --- a/rtl/core/neorv32_xirq.vhd +++ b/rtl/core/neorv32_xirq.vhd @@ -64,16 +64,6 @@ end neorv32_xirq; architecture neorv32_xirq_rtl of neorv32_xirq is - -- IO space: module base address -- - constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit - constant lo_abb_c : natural := index_size_f(xirq_size_c); -- low address boundary bit - - -- access control -- - signal acc_en : std_ulogic; -- module access enable - signal addr : std_ulogic_vector(31 downto 0); -- access address - signal wren : std_ulogic; -- word write enable - signal rden : std_ulogic; -- read enable - -- interface registers -- signal irq_enable : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0); -- r/w: channel enable signal nclr_pending : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0); -- r/w: pending IRQs @@ -103,11 +93,6 @@ begin -- Host Access ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - -- access control -- - acc_en <= '1' when (bus_req_i.addr(hi_abb_c downto lo_abb_c) = xirq_base_c(hi_abb_c downto lo_abb_c)) else '0'; - addr <= xirq_base_c(31 downto lo_abb_c) & bus_req_i.addr(lo_abb_c-1 downto 2) & "00"; -- word aligned - wren <= acc_en and bus_req_i.we; - rden <= acc_en and bus_req_i.re; -- write access -- write_access: process(rstn_i, clk_i) @@ -117,11 +102,11 @@ begin irq_enable <= (others => '0'); elsif rising_edge(clk_i) then nclr_pending <= (others => '1'); - if (wren = '1') then - if (addr = xirq_enable_addr_c) then -- channel-enable + if (bus_req_i.we = '1') then + if (bus_req_i.addr(3 downto 2) = "00") then -- channel-enable irq_enable <= bus_req_i.data(XIRQ_NUM_CH-1 downto 0); end if; - if (addr = xirq_pending_addr_c) then -- clear pending IRQs + if (bus_req_i.addr(3 downto 2) = "01") then -- clear pending IRQs nclr_pending <= bus_req_i.data(XIRQ_NUM_CH-1 downto 0); -- set zero to clear pending IRQ end if; end if; @@ -132,13 +117,13 @@ begin read_access: process(clk_i) begin if rising_edge(clk_i) then - bus_rsp_o.ack <= rden or wren; -- bus handshake + bus_rsp_o.ack <= bus_req_i.re or bus_req_i.we; -- bus handshake bus_rsp_o.data <= (others => '0'); - if (rden = '1') then - case addr is - when xirq_enable_addr_c => bus_rsp_o.data(XIRQ_NUM_CH-1 downto 0) <= irq_enable; -- channel-enable - when xirq_pending_addr_c => bus_rsp_o.data(XIRQ_NUM_CH-1 downto 0) <= irq_pending; -- pending IRQs - when others => bus_rsp_o.data(4 downto 0) <= irq_source; -- IRQ source + if (bus_req_i.re = '1') then + case bus_req_i.addr(3 downto 2) is + when "00" => bus_rsp_o.data(XIRQ_NUM_CH-1 downto 0) <= irq_enable; -- channel-enable + when "01" => bus_rsp_o.data(XIRQ_NUM_CH-1 downto 0) <= irq_pending; -- pending IRQs + when others => bus_rsp_o.data(4 downto 0) <= irq_source; -- IRQ source end case; end if; end if; @@ -222,7 +207,7 @@ begin cpu_irq_o <= '1'; irq_active <= '1'; end if; - elsif (wren = '1') and (addr = xirq_source_addr_c) then -- acknowledge on write access + elsif (bus_req_i.we = '1') and (bus_req_i.addr(3 downto 2) = "10") then -- acknowledge on write access irq_active <= '0'; end if; end if; diff --git a/sw/bootloader/bootloader.c b/sw/bootloader/bootloader.c index 19e093788..5a9b4d1a6 100644 --- a/sw/bootloader/bootloader.c +++ b/sw/bootloader/bootloader.c @@ -124,10 +124,6 @@ #define XIP_EN 1 #endif -/** XIP page base address */ -#ifndef XIP_PAGE_BASE_ADDR - #define XIP_PAGE_BASE_ADDR 0x40000000UL -#endif /**@}*/ @@ -294,7 +290,7 @@ int main(void) { if (neorv32_xip_available()) { neorv32_xip_setup(SPI_FLASH_CLK_PRSC, 0, 0, SPI_FLASH_CMD_READ); neorv32_xip_burst_mode_enable(); - neorv32_xip_start(SPI_FLASH_ADDR_BYTES, XIP_PAGE_BASE_ADDR); + neorv32_xip_start(SPI_FLASH_ADDR_BYTES); } #endif @@ -431,7 +427,7 @@ int main(void) { } #endif else if (c == '?') { - PRINT_TEXT("(c) by Stephan Nolting\ngithub.com/stnolting/neorv32"); + PRINT_TEXT("github.com/stnolting/neorv32"); } else { // unknown command PRINT_TEXT("Invalid CMD"); @@ -476,7 +472,7 @@ void start_app(int boot_xip) { register uint32_t app_base = NEORV32_SYSINFO->ISPACE_BASE; // default = start at beginning of IMEM #if (XIP_EN != 0) if (boot_xip) { - app_base = (uint32_t)(XIP_PAGE_BASE_ADDR + SPI_BOOT_BASE_ADDR); // start from XIP mapped address + app_base = (uint32_t)(XIP_MEM_BASE_ADDRESS + SPI_BOOT_BASE_ADDR); // start from XIP mapped address } #endif @@ -487,12 +483,6 @@ void start_app(int boot_xip) { // wait for UART0 to finish transmitting while (neorv32_uart0_tx_busy()); - // memory sync - if (neorv32_cpu_csr_read(CSR_MXISA) & (1 << CSR_MXISA_ZIFENCEI)) { // Zifenci ISA extension available? - asm volatile ("fence.i"); - } - asm volatile ("fence"); - // start application asm volatile ("jalr ra, %0" : : "r" (app_base)); diff --git a/sw/common/neorv32.ld b/sw/common/neorv32.ld index 9c9f5ea72..20923c250 100644 --- a/sw/common/neorv32.ld +++ b/sw/common/neorv32.ld @@ -63,20 +63,19 @@ __neorv32_ram_size = DEFINED(__neorv32_ram_size) ? __neorv32_ram_size : 8K; /* Default HEAP size (= 0; no heap at all) */ __neorv32_heap_size = DEFINED(__neorv32_heap_size) ? __neorv32_heap_size : 0; -/* Default section base addresses - do not change this unless the hardware-defined address space layout is changed! */ +/* Default section base addresses */ __neorv32_rom_base = DEFINED(__neorv32_rom_base) ? __neorv32_rom_base : 0x00000000; /* = VHDL package's "ispace_base_c" */ __neorv32_ram_base = DEFINED(__neorv32_ram_base) ? __neorv32_ram_base : 0x80000000; /* = VHDL package's "dspace_base_c" */ /* ************************************************************************************************* */ -/* If compiling the bootloader, the rom section is automatically re-mapped to the processor-internal */ +/* If compiling the bootloader, the ROM section is automatically re-mapped to the processor-internal */ /* bootloader ROM address space. */ /* ************************************************************************************************* */ MEMORY { - rom (rx) : ORIGIN = DEFINED(make_bootloader) ? 0xFFFF0000 : __neorv32_rom_base, LENGTH = DEFINED(make_bootloader) ? 32K : __neorv32_rom_size - ram (rwx) : ORIGIN = __neorv32_ram_base, LENGTH = DEFINED(make_bootloader) ? 512 : __neorv32_ram_size - iodev (rw) : ORIGIN = 0xFFFFFE00, LENGTH = 512 /* this is hardware-defined and should not be modified! */ + rom (rx) : ORIGIN = DEFINED(make_bootloader) ? 0xFFFFC000 : __neorv32_rom_base, LENGTH = DEFINED(make_bootloader) ? 8K : __neorv32_rom_size + ram (rwx) : ORIGIN = __neorv32_ram_base, LENGTH = DEFINED(make_bootloader) ? 512 : __neorv32_ram_size } @@ -301,6 +300,4 @@ SECTIONS PROVIDE(__crt0_copy_data_src_begin = LOADADDR(.data)); PROVIDE(__crt0_copy_data_dst_begin = ADDR(.data)); PROVIDE(__crt0_copy_data_dst_end = ADDR(.data) + SIZEOF(.data)); - PROVIDE(__crt0_io_space_begin = ORIGIN(iodev)); - PROVIDE(__crt0_io_space_end = ORIGIN(iodev) + LENGTH(iodev)); } diff --git a/sw/example/demo_blink_led_asm/main.S b/sw/example/demo_blink_led_asm/main.S index 12babd15f..88ec2ee14 100644 --- a/sw/example/demo_blink_led_asm/main.S +++ b/sw/example/demo_blink_led_asm/main.S @@ -3,7 +3,7 @@ /* # ********************************************************************************************* # */ /* # BSD 3-Clause License # */ /* # # */ -/* # Copyright (c) 2022, Stephan Nolting. All rights reserved. # */ +/* # Copyright (c) 2023, 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: # */ @@ -47,15 +47,15 @@ .global main // Memory map -.set GPIO_OUTPUT_LO, 0xFFFFFFC8U // address of the GPIO.OUTPUT_LO register -.set SYSINFO_CKLK, 0xFFFFFFE0U // address of SYSINFO.CLK +.set GPIO_OUTPUT_LO, 0xFFFFFC00U // address of GPIO +.set SYSINFO_CKLK, 0xFFFFFE00U // address of SYSINFO /**********************************************************************//** * Entry point = main **************************************************************************/ main: - li a0, GPIO_OUTPUT_LO // address of the GPIO.OUTPUT_LO register + li a0, GPIO_OUTPUT_LO+8 // address of the GPIO.OUTPUT_LO register li a1, 0 // clear counter loop: @@ -70,7 +70,7 @@ loop: * Delay subroutine using mcycle (waiting for 0.25s) **************************************************************************/ delay: - li t0, SYSINFO_CKLK // address of SYSINFO.CLK + li t0, SYSINFO_CKLK+0 // address of SYSINFO.CLK lw t0, 0(t0) // read SYSINFO.CLK (= CPU clock speed in Hz = tick per second) srli t0, t0, 2 // = ticks per 0.25 seconds csrw mcycle, zero //clear cycle counter (low word) diff --git a/sw/example/demo_xip/main.c b/sw/example/demo_xip/main.c index c3535cde3..00e2d9534 100644 --- a/sw/example/demo_xip/main.c +++ b/sw/example/demo_xip/main.c @@ -48,8 +48,6 @@ /**@{*/ /** UART BAUD rate */ #define BAUD_RATE 19200 -/** XIP page base address (32-bit) */ -#define XIP_PAGE_BASE_ADDR 0x40000000 /** Flash base address (32-bit) */ #define FLASH_BASE 0x00400000 /** Flash address bytes */ @@ -124,7 +122,7 @@ int main() { // configuration note neorv32_uart0_printf("Flash base address: 0x%x\n" "XIP base address: 0x%x\n" - "Flash address bytes: %u\n", (uint32_t)FLASH_BASE, (uint32_t)XIP_PAGE_BASE_ADDR, (uint32_t)FLASH_ABYTES); + "Flash address bytes: %u\n", (uint32_t)FLASH_BASE, (uint32_t)XIP_MEM_BASE_ADDRESS, (uint32_t)FLASH_ABYTES); neorv32_uart0_printf("XIP SPI clock speed: %u Hz\n\n", neorv32_cpu_get_clk_from_prsc(XIP_CLK_PRSC)/2); @@ -151,7 +149,7 @@ int main() { " Navigate to any example program folder (like 'neorv32/sw/example/hello_word').\n" " Compile the program but relocate the instruction to the beginning of the Flash:\n" " make MARCH=rv32i USER_FLAGS+=\"-Wl,--defsym,__neorv32_rom_base=0x%x\" clean_all exe\n\n", - (uint32_t)(XIP_PAGE_BASE_ADDR + FLASH_BASE)); + (uint32_t)(XIP_MEM_BASE_ADDRESS + FLASH_BASE)); neorv32_uart0_printf("Press any key when you are ready.\n\n"); neorv32_uart0_getc(); // wait for any key @@ -201,17 +199,17 @@ int main() { // configure and enable the actual XIP mode // * configure FLASH_ABYTES address bytes send to the SPI flash for addressing - // * map the XIP flash to the address space starting at XIP_PAGE_BASE_ADDR - only the 4 MSBs are relevant here + // * map the XIP flash to the address space starting at XIP_MEM_BASE_ADDRESS - only the 4 MSBs are relevant here // after calling this function the SPI flash is mapped to the processor's address space and is accessible as "normal" // memory-mapped read-only memory - if (neorv32_xip_start(FLASH_ABYTES, XIP_PAGE_BASE_ADDR)) { + if (neorv32_xip_start(FLASH_ABYTES)) { neorv32_uart0_printf("Error! XIP mode configuration error!\n"); return 1; } // since the flash is now mapped to the processor's address space we can dump its content by using normal memory accesses neorv32_uart0_printf("\nRead-back XIP flash content (first 10 words) via memory-mapped access...\n"); - uint32_t flash_base_addr = XIP_PAGE_BASE_ADDR + FLASH_BASE; + uint32_t flash_base_addr = XIP_MEM_BASE_ADDRESS + FLASH_BASE; uint32_t *xip_mem = (uint32_t*)flash_base_addr; asm volatile("fence"); uint32_t i; @@ -230,9 +228,9 @@ int main() { // ---------------------------------------------------------- // finally, jump to the XIP flash's base address we have configured to start execution **from there** - neorv32_uart0_printf("\nStarting Execute In-Place program (@0x%x)...\n", (uint32_t)(XIP_PAGE_BASE_ADDR + FLASH_BASE)); + neorv32_uart0_printf("\nStarting Execute In-Place program (@0x%x)...\n", (uint32_t)(XIP_MEM_BASE_ADDRESS + FLASH_BASE)); asm volatile("fence.i"); - asm volatile ("call %[dest]" : : [dest] "i" (XIP_PAGE_BASE_ADDR + FLASH_BASE)); + asm volatile ("call %[dest]" : : [dest] "i" (XIP_MEM_BASE_ADDRESS + FLASH_BASE)); // this should never be reached diff --git a/sw/example/processor_check/main.c b/sw/example/processor_check/main.c index 1d26bb0d5..d44ab6c7d 100644 --- a/sw/example/processor_check/main.c +++ b/sw/example/processor_check/main.c @@ -47,18 +47,18 @@ * @name User configuration **************************************************************************/ /**@{*/ -/** UART BAUD rate */ +//** UART BAUD rate */ #define BAUD_RATE (19200) //** Reachable unaligned address */ -#define ADDR_UNALIGNED_1 (0x00000001) +#define ADDR_UNALIGNED_1 (0x00000001UL) //** Reachable unaligned address */ -#define ADDR_UNALIGNED_2 (0x00000002) +#define ADDR_UNALIGNED_2 (0x00000002UL) //** Unreachable word-aligned address */ -#define ADDR_UNREACHABLE (IO_BASE_ADDRESS-4) -//**Read-only word-aligned address */ +#define ADDR_UNREACHABLE ((uint32_t)&NEORV32_DM->SREG) +//** Read-only word-aligned address */ #define ADDR_READONLY ((uint32_t)&NEORV32_SYSINFO->CLK) -//** external memory base address */ -#define EXT_MEM_BASE (0xF0000000) +//** External memory base address */ +#define EXT_MEM_BASE (0xF0000000UL) /**@}*/ @@ -90,7 +90,7 @@ void test_ok(void); void test_fail(void); // MCAUSE value that will be NEVER set by the hardware -const uint32_t mcause_never_c = 0x80000000U; // = reserved +const uint32_t mcause_never_c = 0x80000000UL; // = reserved // Global variables (also test initialization of global vars here) /// Global counter for failing tests @@ -232,7 +232,7 @@ int main() { } } else { - PRINT_STANDARD("[skipped, n.a.]\n"); + PRINT_STANDARD("[n.a.]\n"); } neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0); // enable all counters @@ -268,7 +268,7 @@ int main() { } } else { - PRINT_STANDARD("[skipped, n.a.]\n"); + PRINT_STANDARD("[n.a.]\n"); } @@ -292,7 +292,7 @@ int main() { // ---------------------------------------------------------- - // Test standard RISC-V counters + // Test standard RISC-V counters // ---------------------------------------------------------- neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c); PRINT_STANDARD("[%i] Zicntr CNTs ", cnt_test); @@ -363,12 +363,12 @@ int main() { neorv32_cpu_csr_set(CSR_MCOUNTINHIBIT, 0); } else { - PRINT_STANDARD("[skipped, n.a.]\n"); + PRINT_STANDARD("[n.a.]\n"); } // ---------------------------------------------------------- - // Test mcountinhibit: inhibit counter auto-inc + // Test mcountinhibit: inhibit counter auto-inc // ---------------------------------------------------------- neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c); PRINT_STANDARD("[%i] mcountinhibit CSR ", cnt_test); @@ -424,7 +424,7 @@ int main() { } } else { - PRINT_STANDARD("[skipped, n.a.]\n"); + PRINT_STANDARD("[n.a.]\n"); } @@ -459,7 +459,7 @@ int main() { } } else { - PRINT_STANDARD("[skipped, n.a.]\n"); + PRINT_STANDARD("[n.a.]\n"); } @@ -523,7 +523,7 @@ int main() { // Unaligned instruction address // ---------------------------------------------------------- neorv32_cpu_csr_write(CSR_MCAUSE, mcause_never_c); - PRINT_STANDARD("[%i] I_ALG (instr. align) EXC ", cnt_test); + PRINT_STANDARD("[%i] Fetch align EXC ", cnt_test); // skip if C-mode is implemented if ((neorv32_cpu_csr_read(CSR_MISA) & (1< taken %u\n" - "13 EXCs %u\n" - "14 Illegals %u\n", + "00 Instr. %u\n" + "02 Clocks %u\n" + "03 Compr. %u\n" + "04 IF w. %u\n" + "05 II w. %u\n" + "06 ALU w. %u\n" + "07 M LD %u\n" + "08 M ST %u\n" + "09 M w. %u\n" + "10 Jump %u\n" + "11 Branch %u\n" + "12 >taken %u\n" + "13 EXCs %u\n" + "14 Traps %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET), (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE), (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3), @@ -1902,7 +1903,6 @@ int main() { (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12), (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13), (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14)); - } diff --git a/sw/lib/include/neorv32.h b/sw/lib/include/neorv32.h index 3621d292c..1cb790d48 100644 --- a/sw/lib/include/neorv32.h +++ b/sw/lib/include/neorv32.h @@ -184,43 +184,43 @@ enum NEORV32_CLOCK_PRSC_enum { /**********************************************************************//** - * @name Address space sections + * @name Main Address Space Sections **************************************************************************/ /**@{*/ +/** XIP-mapped memory base address */ +#define XIP_MEM_BASE_ADDRESS (0xE0000000U) /** bootloader memory base address */ -#define BOOTLOADER_BASE_ADDRESS (0xFFFF0000U) -/** on-chip debugger complex base address */ -#define OCD_BASE_ADDRESS (0XFFFFF800U) +#define BOOTLOADER_BASE_ADDRESS (0xFFFFC000U) /** peripheral/IO devices memory base address */ -#define IO_BASE_ADDRESS (0xFFFFFE00U) +#define IO_BASE_ADDRESS (0xFFFFE000U) /**@}*/ /**********************************************************************//** - * @name Peripheral/IO Devices - IO Address Space - base addresses + * @name IO Address Space - Peripheral/IO Devices **************************************************************************/ /**@{*/ -#define NEORV32_DM_BASE (0xFFFFF800U) /**< On-Chip Debugger - Debuf Module (OCD) */ -#define NEORV32_CFS_BASE (0xFFFFFE00U) /**< Custom Functions Subsystem (CFS) */ -#define NEORV32_SDI_BASE (0xFFFFFF00U) /**< Serial Data Interface (SDI) */ -#define NEORV32_SLINK_BASE (0xFFFFFF08U) /**< Stream Link Interface (SLINK) */ -#define NEORV32_DMA_BASE (0xFFFFFF10U) /**< Direct Memory Access Controller (DMA) */ -#define NEORV32_CRC_BASE (0xFFFFFF20U) /**< Cyclic Redundancy Check Unit (DMA) */ -#define NEORV32_XIP_BASE (0xFFFFFF40U) /**< Execute In Place Module (XIP) */ -#define NEORV32_PWM_BASE (0xFFFFFF50U) /**< Pulse Width Modulation Controller (PWM) */ -#define NEORV32_GPTMR_BASE (0xFFFFFF60U) /**< General Purpose Timer (GPTMR) */ -#define NEORV32_ONEWIRE_BASE (0xFFFFFF70U) /**< 1-Wire Interface Controller (ONEWIRE) */ -#define NEORV32_XIRQ_BASE (0xFFFFFF80U) /**< External Interrupt Controller (XIRQ) */ -#define NEORV32_MTIME_BASE (0xFFFFFF90U) /**< Machine System Timer (MTIME) */ -#define NEORV32_UART0_BASE (0xFFFFFFA0U) /**< Primary Universal Asynchronous Receiver and Transmitter (UART0) */ -#define NEORV32_SPI_BASE (0xFFFFFFA8U) /**< Serial Peripheral Interface Controller (SPI) */ -#define NEORV32_TWI_BASE (0xFFFFFFB0U) /**< Two-Wire Interface Controller (TWI) */ -#define NEORV32_TRNG_BASE (0xFFFFFFB8U) /**< True Random Number Generator (TRNG) */ -#define NEORV32_WDT_BASE (0xFFFFFFBCU) /**< Watchdog Timer (WDT) */ -#define NEORV32_GPIO_BASE (0xFFFFFFC0U) /**< General Purpose Input/Output Port Controller (GPIO) */ -#define NEORV32_UART1_BASE (0xFFFFFFD0U) /**< Secondary Universal Asynchronous Receiver and Transmitter (UART1) */ -#define NEORV32_NEOLED_BASE (0xFFFFFFD8U) /**< Smart LED Hardware Interface (NEOLED) */ -#define NEORV32_SYSINFO_BASE (0xFFFFFFE0U) /**< System Information Memory (SYSINFO) */ +#define NEORV32_CFS_BASE (0xFFFFEB00U) /**< Custom Functions Subsystem (CFS) */ +#define NEORV32_SLINK_BASE (0xFFFFEC00U) /**< Stream Link Interface (SLINK) */ +#define NEORV32_DMA_BASE (0xFFFFED00U) /**< Direct Memory Access Controller (DMA) */ +#define NEORV32_CRC_BASE (0xFFFFEE00U) /**< Cyclic Redundancy Check Unit (DMA) */ +#define NEORV32_XIP_BASE (0xFFFFEF00U) /**< Execute In Place Module (XIP) */ +#define NEORV32_PWM_BASE (0xFFFFF000U) /**< Pulse Width Modulation Controller (PWM) */ +#define NEORV32_GPTMR_BASE (0xFFFFF100U) /**< General Purpose Timer (GPTMR) */ +#define NEORV32_ONEWIRE_BASE (0xFFFFF200U) /**< 1-Wire Interface Controller (ONEWIRE) */ +#define NEORV32_XIRQ_BASE (0xFFFFF300U) /**< External Interrupt Controller (XIRQ) */ +#define NEORV32_MTIME_BASE (0xFFFFF400U) /**< Machine System Timer (MTIME) */ +#define NEORV32_UART0_BASE (0xFFFFF500U) /**< Primary Universal Asynchronous Receiver and Transmitter (UART0) */ +#define NEORV32_UART1_BASE (0xFFFFF600U) /**< Secondary Universal Asynchronous Receiver and Transmitter (UART1) */ +#define NEORV32_SDI_BASE (0xFFFFF700U) /**< Serial Data Interface (SDI) */ +#define NEORV32_SPI_BASE (0xFFFFF800U) /**< Serial Peripheral Interface Controller (SPI) */ +#define NEORV32_TWI_BASE (0xFFFFF900U) /**< Two-Wire Interface Controller (TWI) */ +#define NEORV32_TRNG_BASE (0xFFFFFA00U) /**< True Random Number Generator (TRNG) */ +#define NEORV32_WDT_BASE (0xFFFFFB00U) /**< Watchdog Timer (WDT) */ +#define NEORV32_GPIO_BASE (0xFFFFFC00U) /**< General Purpose Input/Output Port Controller (GPIO) */ +#define NEORV32_NEOLED_BASE (0xFFFFFD00U) /**< Smart LED Hardware Interface (NEOLED) */ +#define NEORV32_SYSINFO_BASE (0xFFFFFE00U) /**< System Information Memory (SYSINFO) */ +#define NEORV32_DM_BASE (0xFFFFFF00U) /**< On-Chip Debugger - Debug Module (OCD) */ /**@}*/ diff --git a/sw/lib/include/neorv32_xip.h b/sw/lib/include/neorv32_xip.h index 432b539af..e55ca2cca 100644 --- a/sw/lib/include/neorv32_xip.h +++ b/sw/lib/include/neorv32_xip.h @@ -73,11 +73,9 @@ enum NEORV32_XIP_CTRL_enum { XIP_CTRL_XIP_ABYTES_MSB = 12, /**< XIP control register(12) (r/w): Number XIP address bytes (minus 1), MSB */ XIP_CTRL_RD_CMD_LSB = 13, /**< XIP control register(13) (r/w): SPI flash read command, LSB */ XIP_CTRL_RD_CMD_MSB = 20, /**< XIP control register(20) (r/w): SPI flash read command, MSB */ - XIP_CTRL_PAGE_LSB = 21, /**< XIP control register(21) (r/w): XIP memory page, LSB */ - XIP_CTRL_PAGE_MSB = 24, /**< XIP control register(24) (r/w): XIP memory page, MSB */ - XIP_CTRL_SPI_CSEN = 25, /**< XIP control register(25) (r/w): SPI chip-select enable */ - XIP_CTRL_HIGHSPEED = 26, /**< XIP control register(26) (r/w): SPI high-speed mode enable (ignoring XIP_CTRL_PRSC) */ - XIP_CTRL_BURST_EN = 27, /**< XIP control register(27) (r/w): Enable XIP burst mode */ + XIP_CTRL_SPI_CSEN = 21, /**< XIP control register(21) (r/w): SPI chip-select enable */ + XIP_CTRL_HIGHSPEED = 22, /**< XIP control register(22) (r/w): SPI high-speed mode enable (ignoring XIP_CTRL_PRSC) */ + XIP_CTRL_BURST_EN = 23, /**< XIP control register(23) (r/w): Enable XIP burst mode */ XIP_CTRL_PHY_BUSY = 30, /**< XIP control register(20) (r/-): SPI PHY is busy */ XIP_CTRL_XIP_BUSY = 31 /**< XIP control register(31) (r/-): XIP access in progress */ @@ -91,7 +89,7 @@ enum NEORV32_XIP_CTRL_enum { /**@{*/ int neorv32_xip_available(void); void neorv32_xip_setup(int prsc, int cpol, int cpha, uint8_t rd_cmd); -int neorv32_xip_start(int abytes, uint32_t page_base); +int neorv32_xip_start(int abytes); void neorv32_xip_highspeed_enable(void); void neorv32_xip_highspeed_disable(void); void neorv32_xip_burst_mode_enable(void); diff --git a/sw/lib/source/neorv32_xip.c b/sw/lib/source/neorv32_xip.c index 7393ab0b8..f0132b71d 100644 --- a/sw/lib/source/neorv32_xip.c +++ b/sw/lib/source/neorv32_xip.c @@ -105,17 +105,13 @@ void neorv32_xip_setup(int prsc, int cpol, int cpha, uint8_t rd_cmd) { * Enable XIP mode (to allow CPU to _transparently_ fetch data & instructions). * * @param[in] abytes Number of address bytes used to access the SPI flash (1,2,3,4). - * @param[in] page_base XIP memory page base address (top 4 address bits, 0..15). * @return 0 if XIP configuration is OK, -1 if configuration error. **************************************************************************/ -int neorv32_xip_start(int abytes, uint32_t page_base) { +int neorv32_xip_start(int abytes) { - if ((abytes < 1) || (abytes > 4) || // invalid address bytes - (page_base & 0x0FFFFFFFUL) || // invalid granularity - (page_base >= 0xF0000000UL)) { // IO/BOOTROM page + if ((abytes < 1) || (abytes > 4)) { return -1; } - page_base >>= 28; uint32_t ctrl = NEORV32_XIP->CTRL; @@ -128,10 +124,6 @@ int neorv32_xip_start(int abytes, uint32_t page_base) { ctrl &= ~(0xF << XIP_CTRL_SPI_NBYTES_LSB); // clear old configuration ctrl |= ((uint32_t)(abytes+1+4)) << XIP_CTRL_SPI_NBYTES_LSB; // set new configuration - // XIP memory page - ctrl &= ~(0xF << XIP_CTRL_PAGE_LSB); // clear old configuration - ctrl |= ((uint32_t)(page_base & 0xf)) << XIP_CTRL_PAGE_LSB; // set new configuration - ctrl |= 1 << XIP_CTRL_XIP_EN; // enable XIP mode NEORV32_XIP->CTRL = ctrl; diff --git a/sw/ocd-firmware/park_loop.S b/sw/ocd-firmware/park_loop.S index d9fc6fc05..c8ef406cb 100644 --- a/sw/ocd-firmware/park_loop.S +++ b/sw/ocd-firmware/park_loop.S @@ -33,10 +33,10 @@ /* ################################################################################################# */ // debug module (DM) address map -.equ DM_CODE_BASE, 0xfffff800 // base address of debug_module's code ROM (park loop) -.equ DM_PBUF_BASE, 0xfffff840 // base address of debug_module's program buffer (PBUF) -.equ DM_DATA_BASE, 0xfffff880 // base address of debug_module's abstract data buffer (DATA) -.equ DM_SREG_BASE, 0xfffff8C0 // base address of debug_module's status register +.equ DM_CODE_BASE, 0xffffff00 // base address of debug_module's code ROM (park loop) +.equ DM_PBUF_BASE, 0xffffff40 // base address of debug_module's program buffer (PBUF) +.equ DM_DATA_BASE, 0xffffff80 // base address of debug_module's abstract data buffer (DATA) +.equ DM_SREG_BASE, 0xffffffC0 // base address of debug_module's status register // status register (SREG) byte(!!!) offsets .equ SREG_HLT_ACK, ( 0 / 8) // -/w: CPU has halted in debug mode and is waiting in park loop @@ -63,26 +63,26 @@ entry_exception: // BASE + 8: normale entry - ebreak in debug-mode, halt request or return from single-stepped instruction entry_normal: - csrw dscratch0, s0 // backup s0 to dscratch0 so we have a GPR available + csrw dscratch0, x8 // backup x8 to dscratch0 so we have a GPR available // polling loop - waiting for requests park_loop: sb zero, (DM_SREG_BASE+SREG_HLT_ACK)(zero) // ACK that CPU is halted - lbu s0, (DM_SREG_BASE+SREG_EXE_REQ)(zero) // request to execute program buffer? - bnez s0, execute - lbu s0, (DM_SREG_BASE+SREG_RES_REQ)(zero) // request to resume? - beqz s0, park_loop + lbu x8, (DM_SREG_BASE+SREG_EXE_REQ)(zero) // request to execute program buffer? + bnez x8, execute + lbu x8, (DM_SREG_BASE+SREG_RES_REQ)(zero) // request to resume? + beqz x8, park_loop // resume normal operation resume: - sb s0, (DM_SREG_BASE+SREG_RES_ACK)(zero) // ACK that CPU is about to resume - csrr s0, dscratch0 // restore s0 from dscratch0 + sb x8, (DM_SREG_BASE+SREG_RES_ACK)(zero) // ACK that CPU is about to resume + csrr x8, dscratch0 // restore x8 from dscratch0 dret // exit debug mode // execute program buffer execute: sb zero, (DM_SREG_BASE+SREG_EXE_ACK)(zero) // ACK that execution is about to start - csrr s0, dscratch0 // restore s0 from dscratch0 + csrr x8, dscratch0 // restore x8 from dscratch0 fence.i // synchronize ifetch / i-cache & prefetch with memory (PBUF) jalr zero, zero, %lo(DM_PBUF_BASE) // jump to beginning of program buffer (PBUF) diff --git a/sw/svd/README.md b/sw/svd/README.md index 10b7c2e68..a4c549393 100644 --- a/sw/svd/README.md +++ b/sw/svd/README.md @@ -1,6 +1,6 @@ # NEORV32 System View Description (SVD) File -Manually created from `sw/lib/include/neorv32.h`. +Manually created from `sw/lib/include/*. * Format: CMSIS-SVD * Copyright by ARM Ltd, Apache-2.0 License diff --git a/sw/svd/neorv32.svd b/sw/svd/neorv32.svd index 348761234..569f8e69d 100644 --- a/sw/svd/neorv32.svd +++ b/sw/svd/neorv32.svd @@ -38,7 +38,7 @@ CFS Custom functions subsystem CFS - 0xFFFFFE00 + 0xFFFFEB00 CFS_FIRQ1 @@ -121,7 +121,7 @@ SDI Serial data interface controller SDI - 0xFFFFFF00 + 0xFFFFF700 SDI_FIRQ11 @@ -217,7 +217,7 @@ SLINK Stream Link Interface SLINK - 0xFFFFFF08 + 0xFFFFEC00 SLINK_FIRQ14 @@ -344,7 +344,7 @@ DMA Direct memory access controller DMA - 0xFFFFFF10 + 0xFFFFED00 DMA_FIRQ10 @@ -445,7 +445,7 @@ CRC Cyclic redundancy check unit CRC - 0xFFFFFF20 + 0xFFFFEE00 0 @@ -482,7 +482,7 @@ PWM Pulse-width modulation controller PWM - 0xFFFFFF50 + 0xFFFFF000 0 @@ -531,7 +531,7 @@ XIP Execute In Place Module CIP - 0xFFFFFF40 + 0xFFFFEF00 0 @@ -585,24 +585,19 @@ [20:13] SPI flash read command - - XIP_CTRL_XIP_PAGE - [24:21] - XIP memory page - XIP_CTRL_SPI_CSEN - [25:25] + [21:21] SPI chip-select enable XIP_CTRL_HIGHSPEED - [26:26] + [22:22] SPI high-speed mode enable (ignoring XIP_CTRL_PRSC) XIP_CTRL_BURST_EN - [27:27] + [23:23] Enable burst mode (for XIP accesses) @@ -637,7 +632,7 @@ GPTMR General purpose timer GPTMR - 0xFFFFFF60 + 0xFFFFF100 GPTMR_FIRQ12 @@ -688,7 +683,7 @@ ONEWIRE 1-Wire Interface Controller ONEWIRE - 0xFFFFFF70 + 0xFFFFF200 ONEWIRE_FIRQ13 @@ -775,7 +770,7 @@ XIRQ External interrupts controller XIRQ - 0xFFFFFF80 + 0xFFFFF300 XIRQ_FIRQ8 @@ -809,7 +804,7 @@ MTIME Machine timer MTIME - 0xFFFFFF90 + 0xFFFFF400 0 @@ -846,7 +841,7 @@ UART0 Primary universal asynchronous receiver and transmitter UART0 - 0xFFFFFFA0 + 0xFFFFF500 UART0_RX_FIRQ2 UART0_TX_FIRQ3 @@ -976,7 +971,7 @@ UART1 Secondary universal asynchronous receiver and transmitter UART1 - 0xFFFFFFD0 + 0xFFFFF600 UART1_RX_FIRQ4 UART1_TX_FIRQ5 @@ -993,7 +988,7 @@ SPI Serial peripheral interface controller SPI - 0xFFFFFFA8 + 0xFFFFF800 SPI_FIRQ6 @@ -1110,7 +1105,7 @@ TWI Two-wire interface controller SPI - 0xFFFFFFB0 + 0xFFFFF900 TWI_FIRQ7 @@ -1201,7 +1196,7 @@ TRNG True random number generator TRNG - 0xFFFFFFB8 + 0xFFFFFA00 0 @@ -1274,7 +1269,7 @@ WDT Watchdog timer WDT - 0xFFFFFFBC + 0xFFFFFB00 WDT_FIRQ0 @@ -1357,7 +1352,7 @@ GPIO General purpose input/output port GPIO - 0xFFFFFFc0 + 0xFFFFFC00 0 @@ -1396,7 +1391,7 @@ NEOLED Smart LED hardware interface NEOLED - 0xFFFFFFD8 + 0xFFFFFD00 NEOLED_FIRQ9 @@ -1497,7 +1492,7 @@ SYSINFO System configuration information memory SYSINFO - 0xFFFFFFE0 + 0xFFFFFE00 0