Archived
1
0

Initial commit

This commit is contained in:
github-classroom[bot]
2024-02-23 13:01:05 +00:00
committed by GitHub
commit d212040c30
1914 changed files with 1290006 additions and 0 deletions

View File

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2021, 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.

View File

@ -0,0 +1,335 @@
[![NEORV32](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_logo_dark.png)](https://github.com/stnolting/neorv32)
# The NEORV32 RISC-V Processor
[![datasheet (pdf)](https://img.shields.io/badge/data%20sheet-PDF-ffbd00?longCache=true&style=flat-square&logo=asciidoctor)](https://github.com/stnolting/neorv32/releases/tag/nightly)
[![datasheet (html)](https://img.shields.io/badge/-HTML-ffbd00?longCache=true&style=flat-square)](https://stnolting.github.io/neorv32)
[![userguide (pdf)](https://img.shields.io/badge/user%20guide-PDF-ffbd00?longCache=true&style=flat-square&logo=asciidoctor)](https://github.com/stnolting/neorv32/releases/tag/nightly)
[![userguide (html)](https://img.shields.io/badge/-HTML-ffbd00?longCache=true&style=flat-square)](https://stnolting.github.io/neorv32/ug)
[![doxygen](https://img.shields.io/badge/doxygen-HTML-ffbd00?longCache=true&style=flat-square&logo=Doxygen)](https://stnolting.github.io/neorv32/sw/files.html)
[![Gitter](https://img.shields.io/badge/Chat-on%20gitter-4db797.svg?longCache=true&style=flat-square&logo=gitter&logoColor=e8ecef)](https://gitter.im/neorv32/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
1. [Overview](#1-Overview)
* [Key Features](#Project-Key-Features)
* [Status](#status)
2. [Processor/SoC Features](#2-NEORV32-Processor-Features)
* [FPGA Implementation Results](#FPGA-Implementation-Results---Processor)
3. [CPU Features](#3-NEORV32-CPU-Features)
* [Available ISA Extensions](#Available-ISA-Extensions)
* [FPGA Implementation Results](#FPGA-Implementation-Results---CPU)
* [Performance](#Performance)
4. [Software Framework & Tooling](#4-Software-Framework-and-Tooling)
5. [**Getting Started**](#5-Getting-Started) :rocket:
## 1. Overview
![neorv32 Overview](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_processor.png)
The NEORV32 Processor is a **customizable microcontroller-like system on chip (SoC)** that is based on the RISC-V NEORV32 CPU.
The project is intended as auxiliary processor in larger SoC designs or as *ready-to-go* stand-alone
custom microcontroller that even fits into a Lattice iCE40 UltraPlus 5k low-power FPGA running at 24 MHz.
Special focus is paid on **execution safety** to provide defined and predictable behavior at any time.
Therefore, the CPU ensures that all memory access are acknowledged and no invalid/malformed instructions
are executed. Whenever an unexpected situation occurs the application code is informed via precise and resumable hardware exceptions.
:thinking: Want to know more? Check out the [project's rationale](https://stnolting.github.io/neorv32/#_rationale).
:books: For detailed information take a look at the [NEORV32 documentation](https://stnolting.github.io/neorv32/) (online at GitHub-pages).
:label: The project's change log is available in [`CHANGELOG.md`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md).
To see the changes between _official releases_ visit the project's [release page](https://github.com/stnolting/neorv32/releases).
:package: [Exemplary setups](https://github.com/stnolting/neorv32/tree/master/setups) targeting
various FPGA boards and toolchains to get you started.
:kite: Supported by upstream [Zephyr OS](https://docs.zephyrproject.org/latest/boards/riscv/neorv32/doc/index.html) and FreeRTOS.
:bulb: Feel free to open a [new issue](https://github.com/stnolting/neorv32/issues) or start a
[new discussion](https://github.com/stnolting/neorv32/discussions) if you have questions, comments, ideas or if something is
not working as expected. Or have a chat on our [gitter channel](https://gitter.im/neorv32/community).
See how to [contribute](https://github.com/stnolting/neorv32/blob/master/CONTRIBUTING.md).
:rocket: Check out the [quick links below](#5-Getting-Started) or directly jump to the
[*User Guide*](https://stnolting.github.io/neorv32/ug/) to get started
setting up your NEORV32 setup!
### Project Key Features
- [x] all-in-one package: [CPU](#3-NEORV32-CPU-Features) plus [SoC](#2-NEORV32-Processor-Features) plus [Software Framework & Tooling](#4-Software-Framework-and-Tooling)
- [x] completely described in behavioral, platform-independent VHDL - no primitives, macros, etc.
- [x] be as small as possible while being as RISC-V-compliant as possible
- [x] from zero to *printf("hello world!");* - completely open source and documented
- [x] easy to use even for FPGA/RISC-V starters intended to work *out of the box*
### Status
[![release](https://img.shields.io/github/v/release/stnolting/neorv32?longCache=true&style=flat-square&logo=GitHub)](https://github.com/stnolting/neorv32/releases)
[![GitHub Pages](https://img.shields.io/website.svg?label=stnolting.github.io%2Fneorv32&longCache=true&style=flat-square&url=http%3A%2F%2Fstnolting.github.io%2Fneorv32%2Findex.html&logo=GitHub)](https://stnolting.github.io/neorv32)
[![Documentation](https://img.shields.io/github/workflow/status/stnolting/neorv32/Documentation/master?longCache=true&style=flat-square&label=Documentation&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32/actions?query=workflow%3ADocumentation)
\
[![riscv-arch-test](https://img.shields.io/github/workflow/status/stnolting/neorv32/riscv-arch-test/master?longCache=true&style=flat-square&label=riscv-arch-test&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32/actions?query=workflow%3Ariscv-arch-test)
[![Processor](https://img.shields.io/github/workflow/status/stnolting/neorv32/Processor/master?longCache=true&style=flat-square&label=Processor&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32/actions?query=workflow%3AProcessor)
[![Implementation](https://img.shields.io/github/workflow/status/stnolting/neorv32/Implementation/master?longCache=true&style=flat-square&label=Implementation&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32/actions?query=workflow%3AImplementation)
[![Windows](https://img.shields.io/github/workflow/status/stnolting/neorv32/Windows/master?longCache=true&style=flat-square&label=Windows&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32/actions?query=workflow%3AWindows)
[[back to top](#The-NEORV32-RISC-V-Processor)]
## 2. NEORV32 Processor Features
The NEORV32 Processor (top entity: [`rtl/core/neorv32_top.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd))
provides a full-featured SoC build around the NEORV32 CPU. It is highly configurable via generics
to allow a flexible customization according to your needs. Note that all modules listed below are _optional_.
**Memory**
* processor-internal data and instruction memories ([DMEM](https://stnolting.github.io/neorv32/#_data_memory_dmem) /
[IMEM](https://stnolting.github.io/neorv32/#_instruction_memory_imem)) &
cache ([iCACHE](https://stnolting.github.io/neorv32/#_processor_internal_instruction_cache_icache))
* bootloader ([BOOTLDROM](https://stnolting.github.io/neorv32/#_bootloader_rom_bootrom)) with serial user interface
* allows booting application code via UART or from external SPI flash
**Timers**
* machine system timer, 64-bit ([MTIME](https://stnolting.github.io/neorv32/#_machine_system_timer_mtime)), RISC-V spec. compatible
* general purpose 32-bit timer ([GPTMR](https://stnolting.github.io/neorv32/#_general_purpose_timer_gptmr))
* watchdog timer ([WDT](https://stnolting.github.io/neorv32/#_watchdog_timer_wdt))
**Input/Output**
* standard serial interfaces
([UART](https://stnolting.github.io/neorv32/#_primary_universal_asynchronous_receiver_and_transmitter_uart0),
[SPI](https://stnolting.github.io/neorv32/#_serial_peripheral_interface_controller_spi),
[TWI / I²C](https://stnolting.github.io/neorv32/#_two_wire_serial_interface_controller_twi))
* general purpose [GPIO](https://stnolting.github.io/neorv32/#_general_purpose_input_and_output_port_gpio) and
[PWM](https://stnolting.github.io/neorv32/#_pulse_width_modulation_controller_pwm)
* smart LED interface ([NEOLED](https://stnolting.github.io/neorv32/#_smart_led_interface_neoled)) to directly drive _NeoPixel(TM)_ LEDs
**SoC Connectivity**
* 32-bit external bus interface, Wishbone b4 compatible
([WISHBONE](https://stnolting.github.io/neorv32/#_processor_external_memory_interface_wishbone_axi4_lite))
* [wrapper](https://github.com/stnolting/neorv32/blob/master/rtl/system_integration/neorv32_SystemTop_axi4lite.vhd) for AXI4-Lite master interface
* [wrapper](https://github.com/stnolting/neorv32/blob/master/rtl/system_integration/neorv32_SystemTop_AvalonMM.vhd) for Avalon-MM master interface
* 32-bit stream link interface with up to 8 independent RX and TX links
([SLINK](https://stnolting.github.io/neorv32/#_stream_link_interface_slink))
* AXI4-Stream compatible
* external interrupt controller with up to 32 channels
([XIRQ](https://stnolting.github.io/neorv32/#_external_interrupt_controller_xirq))
* custom functions subsystem ([CFS](https://stnolting.github.io/neorv32/#_custom_functions_subsystem_cfs))
for tightly-coupled custom co-processor extensions
**Advanced**
* _true random_ number generator ([TRNG](https://stnolting.github.io/neorv32/#_true_random_number_generator_trng))
* on-chip debugger ([OCD](https://stnolting.github.io/neorv32/#_on_chip_debugger_ocd)) accessible via JTAG interface - implementing
the [*Minimal RISC-V Debug Specification Version 0.13.2*](https://github.com/riscv/riscv-debug-spec)
and compatible with *OpenOCD* and *gdb*
* bus keeper to monitor the CPU's bus transactions ([BUSKEEPER](https://stnolting.github.io/neorv32/#_internal_bus_monitor_buskeeper))
[[back to top](#The-NEORV32-RISC-V-Processor)]
### FPGA Implementation Results - Processor
The hardware resources used by a specific processor setup is defined by the implemented CPU extensions,
the configuration of the peripheral modules and some "glue logic".
Section [_FPGA Implementation Results - Processor Modules_](https://stnolting.github.io/neorv32/#_processor_modules)
of the online datasheet shows the resource utilization of each optional processor module to allow an
estimation of the actual setup's hardware requirements.
The [`setups`](https://github.com/stnolting/neorv32/tree/master/setups) folder provides exemplary FPGA
setups targeting various FPGA boards and toolchains. These setups also provide resource utilization reports for different
SoC configurations. The latest utilization reports for those setups can be found in the report of the
[Implementation Workflow](https://github.com/stnolting/neorv32/actions/workflows/Implementation.yml).
[[back to top](#The-NEORV32-RISC-V-Processor)]
## 3. NEORV32 CPU Features
The CPU (top entity: [`rtl/core/neorv32_cpu.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_cpu.vhd))
implements the RISC-V 32-bit `rv32` ISA with optional extensions (see below). It is compatible to subsets of the
*Unprivileged ISA Specification* [(Version 2.2)](https://github.com/stnolting/neorv32/blob/master/docs/references/riscv-spec.pdf)
and the *Privileged Architecture Specification* [(Version 1.12-draft)](https://github.com/stnolting/neorv32/blob/master/docs/references/riscv-privileged.pdf).
Compatibility is checked by passing the [official RISC-V architecture tests](https://github.com/riscv/riscv-arch-test)
(see [`sim/README`](sim/README.md)).
The core is a little-endian Von-Neumann machine implemented as multi-cycle architecture.
However, the CPU's _front end_ (instruction fetch) and _back end_ (instruction execution) can work independently to increase performance.
Currently, three privilege levels (`machine` and optional `user` and `debug_mode`) are supported. The CPU implements all three standard RISC-V machine
interrupts (`MTI`, `MEI`, `MSI`) plus 16 _fast interrupt requests_ as custom extensions.
It also supports **all** standard RISC-V exceptions (instruction/load/store misaligned address & bus access fault, illegal
instruction, breakpoint, environment calls).
:books: In-depth detailed information regarding the CPU can be found in the
[_Data Sheet: NEORV32 Central Processing Unit_](https://stnolting.github.io/neorv32/#_neorv32_central_processing_unit_cpu).
### Available ISA Extensions
Currently, the following _optional_ RISC-V-compatible ISA extensions are implemented (linked to the according
documentation section). Note that the `X` extension is always enabled.
**RV32
[[`I`](https://stnolting.github.io/neorv32/#_i_base_integer_isa)/
[`E`](https://stnolting.github.io/neorv32/#_e_embedded_cpu)]
[[`A`](https://stnolting.github.io/neorv32/#_a_atomic_memory_access)]
[[`B`](https://stnolting.github.io/neorv32/#_b_bit_manipulation_operations)]
[[`C`](https://stnolting.github.io/neorv32/#_c_compressed_instructions)]
[[`M`](https://stnolting.github.io/neorv32/#_m_integer_multiplication_and_division)]
[[`U`](https://stnolting.github.io/neorv32/#_u_less_privileged_user_mode)]
[[`X`](https://stnolting.github.io/neorv32/#_x_neorv32_specific_custom_extensions)]
[[`Zfinx`](https://stnolting.github.io/neorv32/#_zfinx_single_precision_floating_point_operations)]
[[`Zicsr`](https://stnolting.github.io/neorv32/#_zicsr_control_and_status_register_access_privileged_architecture)]
[[`Zicntr`](https://stnolting.github.io/neorv32/#_zicntr_cpu_base_counters)]
[[`Zihpm`](https://stnolting.github.io/neorv32/#_zihpm_hardware_performance_monitors)]
[[`Zifencei`](https://stnolting.github.io/neorv32/#_zifencei_instruction_stream_synchronization)]
[[`Zmmul`](https://stnolting.github.io/neorv32/#_zmmul_integer_multiplication)]
[[`PMP`](https://stnolting.github.io/neorv32/#_pmp_physical_memory_protection)]
[[`DEBUG`](https://stnolting.github.io/neorv32/#_cpu_debug_mode)]**
:warning: The `B`, `Zfinx` and `Zmmul` RISC-V extensions are frozen but not officially ratified yet. Hence, there is no
upstream gcc support. To circumvent this, the NEORV32 software framework provides _intrinsic libraries_ for these extensions.
[[back to top](#The-NEORV32-RISC-V-Processor)]
### FPGA Implementation Results - CPU
Implementation results for _exemplary_ CPU configuration generated for an **Intel Cyclone IV EP4CE22F17C6N FPGA**
using **Intel Quartus Prime Lite 20.1** ("balanced implementation, Slow 1200mV 0C Model").
| CPU Configuration (version [1.5.7.10](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md)) | LEs | FFs | Memory bits | DSPs (9-bit) | f_max |
|:------------------------|:----:|:----:|:----:|:-:|:-------:|
| `rv32i` | 806 | 359 | 1024 | 0 | 125 MHz |
| `rv32i_Zicsr_Zicntr` | 1729 | 813 | 1024 | 0 | 124 MHz |
| `rv32imac_Zicsr_Zicntr` | 2511 | 1074 | 1024 | 0 | 124 MHz |
:information_source: An incremental list of CPU extension's hardware utilization can found in the
[_Data Sheet: FPGA Implementation Results - CPU_](https://stnolting.github.io/neorv32/#_cpu).
:information_source: The CPU and SoC provide advanced options to optimize for performance, area or energy.
See [_User Guide: Application-Specific Processor Configuration_](https://stnolting.github.io/neorv32/ug/#_application_specific_processor_configuration)
for more information.
[[back to top](#The-NEORV32-RISC-V-Processor)]
### Performance
The NEORV32 CPU is based on a two-stages pipeline architecture (fetch and execute).
The average CPI (cycles per instruction) depends on the instruction mix of a specific applications and also on the
available CPU extensions.
The following table shows the performance results (scores and average CPI) for _exemplary_ CPU configurations executing
2000 iterations of the [CoreMark](https://github.com/stnolting/neorv32/blob/master/sw/example/coremark) CPU benchmark.
| CPU Configuration (version [1.5.7.10](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md)) | CoreMark Score | CoreMarks/MHz | Average CPI |
|:------------------------------------------------|:-----:|:----------:|:--------:|
| _small_ (`rv32i_Zicsr`) | 33.89 | **0.3389** | **4.04** |
| _medium_ (`rv32imc_Zicsr`) | 62.50 | **0.6250** | **5.34** |
| _performance_ (`rv32imc_Zicsr` + perf. options) | 95.23 | **0.9523** | **3.54** |
:information_source: More information regarding the CPU performance can be found in the
[_Data Sheet: CPU Performance_](https://stnolting.github.io/neorv32/#_cpu_performance).
[[back to top](#The-NEORV32-RISC-V-Processor)]
## 4. Software Framework and Tooling
* [core libraries](https://github.com/stnolting/neorv32/tree/master/sw/lib) for high-level usage of the provided functions and peripherals
* application compilation based on GNU makefiles
* gcc-based toolchain ([pre-compiled toolchains available](https://github.com/stnolting/riscv-gcc-prebuilt))
* [SVD file](https://github.com/stnolting/neorv32/tree/master/sw/svd) for advanced debugging and IDE integration
* bootloader with UART interface console
* runtime environment for handling traps
* several [example programs](https://github.com/stnolting/neorv32/tree/master/sw/example) to get started including CoreMark, FreeRTOS and Conway's Game of Life
* doxygen-based documentation, available on [GitHub pages](https://stnolting.github.io/neorv32/sw/files.html)
* supports implementation using open source tooling (GHDL, Yosys and nextpnr; in the future: "Verilog-to-Routing") - both, software and hardware can be
developed and debugged with open source tooling
* [continuous integration](https://github.com/stnolting/neorv32/actions) is available for:
* allowing users to see the expected execution/output of the tools
* ensuring specification compliance
* catching regressions
* providing ready-to-use and up-to-date bitstreams and documentation
:books: Want to know more? Check out [_Data Sheet: Software Framework_](https://stnolting.github.io/neorv32/#_software_framework).
[[back to top](#The-NEORV32-RISC-V-Processor)]
## 5. Getting Started
This overview provides some *quick links* to the most important sections of the
[online Data Sheet](https://stnolting.github.io/neorv32) and the
[online User Guide](https://stnolting.github.io/neorv32/ug).
### :electric_plug: Hardware Overview
* [Rationale](https://stnolting.github.io/neorv32/#_rationale) - NEORV32: why, how come, what for
* [NEORV32 Processor](https://stnolting.github.io/neorv32/#_neorv32_processor_soc) - the SoC
* [Top Entity - Signals](https://stnolting.github.io/neorv32/#_processor_top_entity_signals) - how to connect to the processor
* [Top Entity - Generics](https://stnolting.github.io/neorv32/#_processor_top_entity_generics) - configuration options
* [Address Space](https://stnolting.github.io/neorv32/#_address_space) - memory layout and boot configuration
* [SoC Modules](https://stnolting.github.io/neorv32/#_processor_internal_modules) - available peripheral modules and memories
* [On-Chip Debugger](https://stnolting.github.io/neorv32/#_on_chip_debugger_ocd) - online & in-system debugging of the processor via JTAG
* [NEORV32 CPU](https://stnolting.github.io/neorv32/#_neorv32_central_processing_unit_cpu) - the CPU
* [RISC-V compatibility](https://stnolting.github.io/neorv32/#_risc_v_compatibility) - what is compatible to the specs. and what is not
* [Full Virtualization](https://stnolting.github.io/neorv32/#_full_virtualization) - hardware execution safety
* [ISA and Extensions](https://stnolting.github.io/neorv32/#_instruction_sets_and_extensions) - available RISC-V ISA extensions
* [CSRs](https://stnolting.github.io/neorv32/#_control_and_status_registers_csrs) - control and status registers
* [Traps](https://stnolting.github.io/neorv32/#_traps_exceptions_and_interrupts) - interrupts and exceptions
### :floppy_disk: Software Overview
* [Example Programs](https://github.com/stnolting/neorv32/tree/master/sw/example) - test program execution on your setup
* [Core Libraries](https://stnolting.github.io/neorv32/#_core_libraries) - high-level functions for accessing the processor's peripherals
* [Software Framework Documentation](https://stnolting.github.io/neorv32/sw/files.html) - `doxygen`-based documentation
* [Application Makefiles](https://stnolting.github.io/neorv32/#_application_makefile) - turning your application into an executable
* [Bootloader](https://stnolting.github.io/neorv32/#_bootloader) - the build-in NEORV32 bootloader
### :rocket: User Guide
* [Toolchain Setup](https://stnolting.github.io/neorv32/ug/#_software_toolchain_setup) - install and setup RISC-V gcc
* [General Hardware Setup](https://stnolting.github.io/neorv32/ug/#_general_hardware_setup) - setup a new NEORV32 EDA project
* [General Software Setup](https://stnolting.github.io/neorv32/ug/#_general_software_framework_setup) - configure the software framework
* [Application Compilation](https://stnolting.github.io/neorv32/ug/#_application_program_compilation) - compile an application using `make`
* [Upload via Bootloader](https://stnolting.github.io/neorv32/ug/#_uploading_and_starting_of_a_binary_executable_image_via_uart) - upload and execute executables
* [Application-Specific Processor Configuration](https://stnolting.github.io/neorv32/ug/#_application_specific_processor_configuration) - tailor the processor to your needs
* [Adding Custom Hardware Modules](https://stnolting.github.io/neorv32/ug/#_adding_custom_hardware_modules) - add _your_ custom hardware
* [Debugging via the On-Chip Debugger](https://stnolting.github.io/neorv32/ug/#_debugging_using_the_on_chip_debugger) - step through code *online* and *in-system*
* [Simulation](https://stnolting.github.io/neorv32/ug/#_simulating_the_processor) - simulate the whole SoC
* [Hello World!](https://stnolting.github.io/neorv32/ug/index.html#_hello_world) - run a quick _"hello world"_ simulation
### :copyright: Legal
[![license](https://img.shields.io/github/license/stnolting/neorv32?longCache=true&style=flat-square)](https://github.com/stnolting/neorv32/blob/master/LICENSE)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5018888.svg)](https://doi.org/10.5281/zenodo.5018888)
* [Overview](https://stnolting.github.io/neorv32/#_legal) - license, disclaimer, limitation of liability for external links, proprietary notice, ...
* [Citing](https://stnolting.github.io/neorv32/#_citing) - citing information
* [Impressum](https://github.com/stnolting/neorv32/blob/master/docs/impressum.md) - imprint
[[back to top](#The-NEORV32-RISC-V-Processor)]
## Acknowledgements
**A big shout-out goes to the community and all the [contributors](https://github.com/stnolting/neorv32/graphs/contributors), who helped improving this project! :heart:**
[RISC-V](https://riscv.org/) - Instruction Sets Want To Be Free!
Continuous integration provided by [:octocat: GitHub Actions](https://github.com/features/actions) and powered by [GHDL](https://github.com/ghdl/ghdl).

Binary file not shown.

Binary file not shown.

View File

View File

View File

@ -0,0 +1,34 @@
## VHDL Source Folders
### [`core`](https://github.com/stnolting/neorv32/tree/master/rtl/core)
This folder contains the core VHDL files for the NEORV32 CPU and the NEORV32 Processor.
When creating a new synthesis/simulation project make sure that all `*.vhd` files from this folder are added to a
*new design library* called `neorv32`.
:warning: The sub-folder [`core/mem`](https://github.com/stnolting/neorv32/tree/master/rtl/core/mem)
contains the _platform-agnostic_ VHDL architectures of the processor-internal memories.
You can _replace_ inclusion of these files by platform-optimized memory architectures.
### [`processor_templates`](https://github.com/stnolting/neorv32/tree/master/rtl/processor_templates`)
Contains pre-configured "SoC" templates that instantiate the processor's top entity from `core`.
These templates can be instantiated directly within a FPGA-specific board wrapper.
### [`system_integration`](https://github.com/stnolting/neorv32/tree/master/rtl/system_integration`)
Top entities in this folder provide the same peripheral/IO signals and configuration generics as the default
processor top entity from `core`, but feature a different interface type.
For example: an **AXI4-Lite**-compatible bus interface instead of the default Wishbone bus interface
or a top entity with _resolved_ port signal types.
### [`test_setups`](https://github.com/stnolting/neorv32/tree/master/rtl/test_setups`)
Minimal test setups (FPGA- and board-independent) for the processor. See the
[README](https://github.com/stnolting/neorv32/tree/master/rtl/test_setups)
in that folder for more information. Note that these test setups are used in the
[NEORV32 USer Guide](https://stnolting.github.io/neorv32/ug).

View File

@ -0,0 +1,14 @@
# Processor Memory Source Files
This folder provides the architecture-only VHDL sources for the processor-internal memories
(instruction memory "IMEM", data memory "DMEM"). Different implementations are available - but
only **one** version of each (IMEM and DMEM) has to be added as actual source files.
For the first implementation the `*.default.vhd` files should be selected. The HDL style for describing
memories used by these files has proven **platform-independence** across several FPGA architectures and toolchains.
If synthesis fails to infer actual block RAM resources from these default files, try the legacy `*.cyclone2.vhd` files, which
provide a different HDL style. These files are intended for legacy support of older Intel/Altera Quartus versions (13.0 and older). However,
these files do **not** use platform-specific macros or primitives - so they might also work for other FPGAs and toolchains.
:warning: Make sure to add the selected files from this folder also to the `neorv32` design library.

View File

@ -0,0 +1,130 @@
-- #################################################################################################
-- # << NEORV32 - Processor-internal data memory (DMEM) >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
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 addr_ff : 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 --
-- problems with 32-bit memories that provide dedicated byte-enable signals AND/OR with multi-dimensional arrays. --
-- -------------------------------------------------------------------------------------------------------------- --
-- RAM - not initialized at all --
signal mem_ram_b0 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b1 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b2 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b3 : mem8_t(0 to DMEM_SIZE/4-1);
-- read data --
signal mem_ram_b0_rd, mem_ram_b1_rd, mem_ram_b2_rd, mem_ram_b3_rd : std_ulogic_vector(7 downto 0);
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using CYCLONE-2-optimized HDL style DMEM." severity note;
assert false report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal DMEM (RAM, " & natural'image(DMEM_SIZE) & " bytes)." severity note;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = DMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
addr <= addr_i(index_size_f(DMEM_SIZE/4)+1 downto 2); -- word aligned
-- Memory Access --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_access: process(clk_i)
begin
if rising_edge(clk_i) then
addr_ff <= addr;
if (acc_en = '1') then -- reduce switching activity when not accessed
if (wren_i = '1') and (ben_i(0) = '1') then -- byte 0
mem_ram_b0(to_integer(unsigned(addr))) <= data_i(07 downto 00);
end if;
if (wren_i = '1') and (ben_i(1) = '1') then -- byte 1
mem_ram_b1(to_integer(unsigned(addr))) <= data_i(15 downto 08);
end if;
if (wren_i = '1') and (ben_i(2) = '1') then -- byte 2
mem_ram_b2(to_integer(unsigned(addr))) <= data_i(23 downto 16);
end if;
if (wren_i = '1') and (ben_i(3) = '1') then -- byte 3
mem_ram_b3(to_integer(unsigned(addr))) <= data_i(31 downto 24);
end if;
end if;
end if;
end process mem_access;
-- sync(!) read - alternative HDL style --
mem_ram_b0_rd <= mem_ram_b0(to_integer(unsigned(addr_ff)));
mem_ram_b1_rd <= mem_ram_b1(to_integer(unsigned(addr_ff)));
mem_ram_b2_rd <= mem_ram_b2(to_integer(unsigned(addr_ff)));
mem_ram_b3_rd <= mem_ram_b3(to_integer(unsigned(addr_ff)));
-- Bus Feedback ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
bus_feedback: process(clk_i)
begin
if rising_edge(clk_i) then
rden <= acc_en and rden_i;
ack_o <= acc_en and (rden_i or wren_i);
end if;
end process bus_feedback;
-- pack --
rdata <= mem_ram_b3_rd & mem_ram_b2_rd & mem_ram_b1_rd & mem_ram_b0_rd;
-- output gate --
data_o <= rdata when (rden = '1') else (others => '0');
end neorv32_dmem_rtl;

View File

@ -0,0 +1,132 @@
-- #################################################################################################
-- # << NEORV32 - Processor-internal data memory (DMEM) >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
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);
-- -------------------------------------------------------------------------------------------------------------- --
-- The memory (RAM) is built from 4 individual byte-wide memories b0..b3, since some synthesis tools have --
-- problems with 32-bit memories that provide dedicated byte-enable signals AND/OR with multi-dimensional arrays. --
-- -------------------------------------------------------------------------------------------------------------- --
-- RAM - not initialized at all --
signal mem_ram_b0 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b1 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b2 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b3 : mem8_t(0 to DMEM_SIZE/4-1);
-- read data --
signal mem_ram_b0_rd, mem_ram_b1_rd, mem_ram_b2_rd, mem_ram_b3_rd : std_ulogic_vector(7 downto 0);
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using DEFAULT platform-agnostic DMEM." severity note;
assert false report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal DMEM (RAM, " & natural'image(DMEM_SIZE) & " bytes)." severity note;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = DMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
addr <= addr_i(index_size_f(DMEM_SIZE/4)+1 downto 2); -- word aligned
-- Memory Access --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- this RAM style should not require "no_rw_check" attributes as the read-after-write behavior
-- is intended to be defined implicitly via the if-WRITE-else-READ construct
if (acc_en = '1') then -- reduce switching activity when not accessed
if (wren_i = '1') and (ben_i(0) = '1') then -- byte 0
mem_ram_b0(to_integer(unsigned(addr))) <= data_i(07 downto 00);
else
mem_ram_b0_rd <= mem_ram_b0(to_integer(unsigned(addr)));
end if;
if (wren_i = '1') and (ben_i(1) = '1') then -- byte 1
mem_ram_b1(to_integer(unsigned(addr))) <= data_i(15 downto 08);
else
mem_ram_b1_rd <= mem_ram_b1(to_integer(unsigned(addr)));
end if;
if (wren_i = '1') and (ben_i(2) = '1') then -- byte 2
mem_ram_b2(to_integer(unsigned(addr))) <= data_i(23 downto 16);
else
mem_ram_b2_rd <= mem_ram_b2(to_integer(unsigned(addr)));
end if;
if (wren_i = '1') and (ben_i(3) = '1') then -- byte 3
mem_ram_b3(to_integer(unsigned(addr))) <= data_i(31 downto 24);
else
mem_ram_b3_rd <= mem_ram_b3(to_integer(unsigned(addr)));
end if;
end if;
end if;
end process mem_access;
-- Bus Feedback ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
bus_feedback: process(clk_i)
begin
if rising_edge(clk_i) then
rden <= acc_en and rden_i;
ack_o <= acc_en and (rden_i or wren_i);
end if;
end process bus_feedback;
-- pack --
rdata <= mem_ram_b3_rd & mem_ram_b2_rd & mem_ram_b1_rd & mem_ram_b0_rd;
-- output gate --
data_o <= rdata when (rden = '1') else (others => '0');
end neorv32_dmem_rtl;

View File

@ -0,0 +1,176 @@
-- #################################################################################################
-- # << NEORV32 - Processor-internal instruction memory (IMEM) >> #
-- # ********************************************************************************************* #
-- # This memory optionally includes the in-place executable image of the application. See the #
-- # processor's documentary to get more information. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
use neorv32.neorv32_application_image.all; -- this file is generated by the image generator
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 addr_ff : std_ulogic_vector(index_size_f(IMEM_SIZE/4)-1 downto 0);
-- --------------------------- --
-- IMEM as pre-initialized ROM --
-- --------------------------- --
-- application (image) size in bytes --
constant imem_app_size_c : natural := (application_init_image'length)*4;
-- ROM - initialized with executable code --
constant mem_rom : mem32_t(0 to IMEM_SIZE/4-1) := mem32_init_f(application_init_image, IMEM_SIZE/4);
-- read data --
signal mem_rom_rd : std_ulogic_vector(31 downto 0);
-- -------------------------------------------------------------------------------------------------------------- --
-- The memory (RAM) is built from 4 individual byte-wide memories b0..b3, since some synthesis tools have --
-- problems with 32-bit memories that provide dedicated byte-enable signals AND/OR with multi-dimensional arrays. --
-- -------------------------------------------------------------------------------------------------------------- --
-- RAM - not initialized at all --
signal mem_ram_b0 : mem8_t(0 to IMEM_SIZE/4-1);
signal mem_ram_b1 : mem8_t(0 to IMEM_SIZE/4-1);
signal mem_ram_b2 : mem8_t(0 to IMEM_SIZE/4-1);
signal mem_ram_b3 : mem8_t(0 to IMEM_SIZE/4-1);
-- read data --
signal mem_b0_rd, mem_b1_rd, mem_b2_rd, mem_b3_rd : std_ulogic_vector(7 downto 0);
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using CYCLONE-2-optimized HDL style IMEM." severity note;
assert not (IMEM_AS_IROM = true) report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as ROM (" & natural'image(IMEM_SIZE) &
" bytes), pre-initialized with application (" & natural'image(imem_app_size_c) & " bytes)." severity note;
--
assert not (IMEM_AS_IROM = false) report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as blank RAM (" & natural'image(IMEM_SIZE) &
" bytes)." severity note;
--
assert not ((IMEM_AS_IROM = true) and (imem_app_size_c > IMEM_SIZE)) report "NEORV32 PROCESSOR CONFIG ERROR: Application (image = " & natural'image(imem_app_size_c) &
" bytes) does not fit into processor-internal IMEM (ROM = " & natural'image(IMEM_SIZE) & " bytes)!" severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = IMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
addr <= addr_i(index_size_f(IMEM_SIZE/4)+1 downto 2); -- word aligned
-- Implement IMEM as pre-initialized ROM --------------------------------------------------
-- -------------------------------------------------------------------------------------------
imem_rom:
if (IMEM_AS_IROM = true) generate
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;
end if;
end process mem_access;
-- read data --
rdata <= mem_rom_rd;
end generate;
-- Implement IMEM as not-initialized RAM --------------------------------------------------
-- -------------------------------------------------------------------------------------------
imem_ram:
if (IMEM_AS_IROM = false) generate
mem_access: process(clk_i)
begin
if rising_edge(clk_i) then
addr_ff <= addr;
if (acc_en = '1') then -- reduce switching activity when not accessed
if (wren_i = '1') and (ben_i(0) = '1') then -- byte 0
mem_ram_b0(to_integer(unsigned(addr))) <= data_i(07 downto 00);
end if;
if (wren_i = '1') and (ben_i(1) = '1') then -- byte 1
mem_ram_b1(to_integer(unsigned(addr))) <= data_i(15 downto 08);
end if;
if (wren_i = '1') and (ben_i(2) = '1') then -- byte 2
mem_ram_b2(to_integer(unsigned(addr))) <= data_i(23 downto 16);
end if;
if (wren_i = '1') and (ben_i(3) = '1') then -- byte 3
mem_ram_b3(to_integer(unsigned(addr))) <= data_i(31 downto 24);
end if;
end if;
end if;
end process mem_access;
-- sync(!) read - alternative HDL style --
mem_b0_rd <= mem_ram_b0(to_integer(unsigned(addr_ff)));
mem_b1_rd <= mem_ram_b1(to_integer(unsigned(addr_ff)));
mem_b2_rd <= mem_ram_b2(to_integer(unsigned(addr_ff)));
mem_b3_rd <= mem_ram_b3(to_integer(unsigned(addr_ff)));
-- pack --
rdata <= mem_b3_rd & mem_b2_rd & mem_b1_rd & mem_b0_rd;
end generate;
-- Bus Feedback ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
bus_feedback: process(clk_i)
begin
if rising_edge(clk_i) then
rden <= acc_en and rden_i;
if (IMEM_AS_IROM = true) then
ack_o <= acc_en and rden_i;
else
ack_o <= acc_en and (rden_i or wren_i);
end if;
end if;
end process bus_feedback;
-- output gate --
data_o <= rdata when (rden = '1') else (others => '0');
end neorv32_imem_rtl;

View File

@ -0,0 +1,179 @@
-- #################################################################################################
-- # << NEORV32 - Processor-internal instruction memory (IMEM) >> #
-- # ********************************************************************************************* #
-- # This memory optionally includes the in-place executable image of the application. See the #
-- # processor's documentary to get more information. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
use neorv32.neorv32_application_image.all; -- this file is generated by the image generator
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);
-- --------------------------- --
-- IMEM as pre-initialized ROM --
-- --------------------------- --
-- application (image) size in bytes --
constant imem_app_size_c : natural := (application_init_image'length)*4;
-- ROM - initialized with executable code --
constant mem_rom : mem32_t(0 to IMEM_SIZE/4-1) := mem32_init_f(application_init_image, IMEM_SIZE/4);
-- read data --
signal mem_rom_rd : std_ulogic_vector(31 downto 0);
-- -------------------------------------------------------------------------------------------------------------- --
-- The memory (RAM) is built from 4 individual byte-wide memories b0..b3, since some synthesis tools have --
-- problems with 32-bit memories that provide dedicated byte-enable signals AND/OR with multi-dimensional arrays. --
-- -------------------------------------------------------------------------------------------------------------- --
-- RAM - not initialized at all --
signal mem_ram_b0 : mem8_t(0 to IMEM_SIZE/4-1);
signal mem_ram_b1 : mem8_t(0 to IMEM_SIZE/4-1);
signal mem_ram_b2 : mem8_t(0 to IMEM_SIZE/4-1);
signal mem_ram_b3 : mem8_t(0 to IMEM_SIZE/4-1);
-- read data --
signal mem_b0_rd, mem_b1_rd, mem_b2_rd, mem_b3_rd : std_ulogic_vector(7 downto 0);
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using DEFAULT platform-agnostic IMEM." severity note;
assert not (IMEM_AS_IROM = true) report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as ROM (" & natural'image(IMEM_SIZE) &
" bytes), pre-initialized with application (" & natural'image(imem_app_size_c) & " bytes)." severity note;
--
assert not (IMEM_AS_IROM = false) report "NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as blank RAM (" & natural'image(IMEM_SIZE) &
" bytes)." severity note;
--
assert not ((IMEM_AS_IROM = true) and (imem_app_size_c > IMEM_SIZE)) report "NEORV32 PROCESSOR CONFIG ERROR: Application (image = " & natural'image(imem_app_size_c) &
" bytes) does not fit into processor-internal IMEM (ROM = " & natural'image(IMEM_SIZE) & " bytes)!" severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = IMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
addr <= addr_i(index_size_f(IMEM_SIZE/4)+1 downto 2); -- word aligned
-- Implement IMEM as pre-initialized ROM --------------------------------------------------
-- -------------------------------------------------------------------------------------------
imem_rom:
if (IMEM_AS_IROM = true) generate
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;
end if;
end process mem_access;
-- read data --
rdata <= mem_rom_rd;
end generate;
-- Implement IMEM as not-initialized RAM --------------------------------------------------
-- -------------------------------------------------------------------------------------------
imem_ram:
if (IMEM_AS_IROM = false) generate
mem_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- this RAM style should not require "no_rw_check" attributes as the read-after-write behavior
-- is intended to be defined implicitly via the if-WRITE-else-READ construct
if (acc_en = '1') then -- reduce switching activity when not accessed
if (wren_i = '1') and (ben_i(0) = '1') then -- byte 0
mem_ram_b0(to_integer(unsigned(addr))) <= data_i(07 downto 00);
else
mem_b0_rd <= mem_ram_b0(to_integer(unsigned(addr)));
end if;
if (wren_i = '1') and (ben_i(1) = '1') then -- byte 1
mem_ram_b1(to_integer(unsigned(addr))) <= data_i(15 downto 08);
else
mem_b1_rd <= mem_ram_b1(to_integer(unsigned(addr)));
end if;
if (wren_i = '1') and (ben_i(2) = '1') then -- byte 2
mem_ram_b2(to_integer(unsigned(addr))) <= data_i(23 downto 16);
else
mem_b2_rd <= mem_ram_b2(to_integer(unsigned(addr)));
end if;
if (wren_i = '1') and (ben_i(3) = '1') then -- byte 3
mem_ram_b3(to_integer(unsigned(addr))) <= data_i(31 downto 24);
else
mem_b3_rd <= mem_ram_b3(to_integer(unsigned(addr)));
end if;
end if;
end if;
end process mem_access;
-- read data --
rdata <= mem_b3_rd & mem_b2_rd & mem_b1_rd & mem_b0_rd;
end generate;
-- Bus Feedback ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
bus_feedback: process(clk_i)
begin
if rising_edge(clk_i) then
rden <= acc_en and rden_i;
if (IMEM_AS_IROM = true) then
ack_o <= acc_en and rden_i;
else
ack_o <= acc_en and (rden_i or wren_i);
end if;
end if;
end process bus_feedback;
-- output gate --
data_o <= rdata when (rden = '1') else (others => '0');
end neorv32_imem_rtl;

View File

@ -0,0 +1,883 @@
-- The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32
-- Auto-generated memory init file (for APPLICATION) from source file <blink_led/main.bin>
-- Size: 3468 bytes
library ieee;
use ieee.std_logic_1164.all;
library neorv32;
use neorv32.neorv32_package.all;
package neorv32_application_image is
constant application_init_image : mem32_t := (
00000000 => x"00000037",
00000001 => x"80002117",
00000002 => x"ff810113",
00000003 => x"80000197",
00000004 => x"7f418193",
00000005 => x"00000517",
00000006 => x"12050513",
00000007 => x"30551073",
00000008 => x"34151073",
00000009 => x"30001073",
00000010 => x"30401073",
00000011 => x"30601073",
00000012 => x"ffa00593",
00000013 => x"32059073",
00000014 => x"b0001073",
00000015 => x"b8001073",
00000016 => x"b0201073",
00000017 => x"b8201073",
00000018 => x"00000093",
00000019 => x"00000213",
00000020 => x"00000293",
00000021 => x"00000313",
00000022 => x"00000393",
00000023 => x"00000713",
00000024 => x"00000793",
00000025 => x"00000813",
00000026 => x"00000893",
00000027 => x"00000913",
00000028 => x"00000993",
00000029 => x"00000a13",
00000030 => x"00000a93",
00000031 => x"00000b13",
00000032 => x"00000b93",
00000033 => x"00000c13",
00000034 => x"00000c93",
00000035 => x"00000d13",
00000036 => x"00000d93",
00000037 => x"00000e13",
00000038 => x"00000e93",
00000039 => x"00000f13",
00000040 => x"00000f93",
00000041 => x"00000417",
00000042 => x"d5c40413",
00000043 => x"00000497",
00000044 => x"f5448493",
00000045 => x"00042023",
00000046 => x"00440413",
00000047 => x"fe941ce3",
00000048 => x"80000597",
00000049 => x"f4058593",
00000050 => x"87418613",
00000051 => x"00c5d863",
00000052 => x"00058023",
00000053 => x"00158593",
00000054 => x"ff5ff06f",
00000055 => x"00001597",
00000056 => x"cb058593",
00000057 => x"80000617",
00000058 => x"f1c60613",
00000059 => x"80000697",
00000060 => x"f1468693",
00000061 => x"00d65c63",
00000062 => x"00058703",
00000063 => x"00e60023",
00000064 => x"00158593",
00000065 => x"00160613",
00000066 => x"fedff06f",
00000067 => x"00000513",
00000068 => x"00000593",
00000069 => x"06c000ef",
00000070 => x"34051073",
00000071 => x"00000093",
00000072 => x"00008463",
00000073 => x"000080e7",
00000074 => x"30047073",
00000075 => x"10500073",
00000076 => x"ffdff06f",
00000077 => x"ff810113",
00000078 => x"00812023",
00000079 => x"00912223",
00000080 => x"34202473",
00000081 => x"02044663",
00000082 => x"34102473",
00000083 => x"00041483",
00000084 => x"0034f493",
00000085 => x"00240413",
00000086 => x"34141073",
00000087 => x"00300413",
00000088 => x"00941863",
00000089 => x"34102473",
00000090 => x"00240413",
00000091 => x"34141073",
00000092 => x"00012403",
00000093 => x"00412483",
00000094 => x"00810113",
00000095 => x"30200073",
00000096 => x"00005537",
00000097 => x"ff010113",
00000098 => x"00000613",
00000099 => x"00000593",
00000100 => x"b0050513",
00000101 => x"00112623",
00000102 => x"088000ef",
00000103 => x"780000ef",
00000104 => x"00050c63",
00000105 => x"730000ef",
00000106 => x"00001537",
00000107 => x"ac850513",
00000108 => x"134000ef",
00000109 => x"020000ef",
00000110 => x"00001537",
00000111 => x"aa450513",
00000112 => x"124000ef",
00000113 => x"00c12083",
00000114 => x"00100513",
00000115 => x"01010113",
00000116 => x"00008067",
00000117 => x"ff010113",
00000118 => x"00000513",
00000119 => x"00000593",
00000120 => x"00112623",
00000121 => x"00812423",
00000122 => x"744000ef",
00000123 => x"00000513",
00000124 => x"00150413",
00000125 => x"00000593",
00000126 => x"0ff57513",
00000127 => x"730000ef",
00000128 => x"0c800513",
00000129 => x"164000ef",
00000130 => x"00040513",
00000131 => x"fe5ff06f",
00000132 => x"fe802503",
00000133 => x"01255513",
00000134 => x"00157513",
00000135 => x"00008067",
00000136 => x"ff010113",
00000137 => x"00812423",
00000138 => x"00912223",
00000139 => x"00112623",
00000140 => x"fa002023",
00000141 => x"fe002783",
00000142 => x"00058413",
00000143 => x"00151593",
00000144 => x"00078513",
00000145 => x"00060493",
00000146 => x"7b0000ef",
00000147 => x"01051513",
00000148 => x"000017b7",
00000149 => x"01055513",
00000150 => x"00000713",
00000151 => x"ffe78793",
00000152 => x"04a7e463",
00000153 => x"0034f793",
00000154 => x"00347413",
00000155 => x"fff50513",
00000156 => x"01479793",
00000157 => x"01641413",
00000158 => x"00f567b3",
00000159 => x"0087e7b3",
00000160 => x"01871713",
00000161 => x"00c12083",
00000162 => x"00812403",
00000163 => x"00e7e7b3",
00000164 => x"10000737",
00000165 => x"00e7e7b3",
00000166 => x"faf02023",
00000167 => x"00412483",
00000168 => x"01010113",
00000169 => x"00008067",
00000170 => x"ffe70693",
00000171 => x"0fd6f693",
00000172 => x"00069a63",
00000173 => x"00355513",
00000174 => x"00170713",
00000175 => x"0ff77713",
00000176 => x"fa1ff06f",
00000177 => x"00155513",
00000178 => x"ff1ff06f",
00000179 => x"00040737",
00000180 => x"fa002783",
00000181 => x"00e7f7b3",
00000182 => x"fe079ce3",
00000183 => x"faa02223",
00000184 => x"00008067",
00000185 => x"ff010113",
00000186 => x"00812423",
00000187 => x"01212023",
00000188 => x"00112623",
00000189 => x"00912223",
00000190 => x"00050413",
00000191 => x"00a00913",
00000192 => x"00044483",
00000193 => x"00140413",
00000194 => x"00049e63",
00000195 => x"00c12083",
00000196 => x"00812403",
00000197 => x"00412483",
00000198 => x"00012903",
00000199 => x"01010113",
00000200 => x"00008067",
00000201 => x"01249663",
00000202 => x"00d00513",
00000203 => x"fa1ff0ef",
00000204 => x"00048513",
00000205 => x"f99ff0ef",
00000206 => x"fc9ff06f",
00000207 => x"ff010113",
00000208 => x"c81026f3",
00000209 => x"c0102773",
00000210 => x"c81027f3",
00000211 => x"fed79ae3",
00000212 => x"00e12023",
00000213 => x"00f12223",
00000214 => x"00012503",
00000215 => x"00412583",
00000216 => x"01010113",
00000217 => x"00008067",
00000218 => x"fd010113",
00000219 => x"00a12623",
00000220 => x"fe002503",
00000221 => x"3e800593",
00000222 => x"02112623",
00000223 => x"02812423",
00000224 => x"02912223",
00000225 => x"03212023",
00000226 => x"01312e23",
00000227 => x"66c000ef",
00000228 => x"00c12603",
00000229 => x"00000693",
00000230 => x"00000593",
00000231 => x"5c4000ef",
00000232 => x"00050413",
00000233 => x"00058993",
00000234 => x"f95ff0ef",
00000235 => x"00058913",
00000236 => x"00050493",
00000237 => x"f89ff0ef",
00000238 => x"00b96663",
00000239 => x"05259263",
00000240 => x"04a4f063",
00000241 => x"008484b3",
00000242 => x"0084b433",
00000243 => x"01390933",
00000244 => x"01240433",
00000245 => x"f69ff0ef",
00000246 => x"fe85eee3",
00000247 => x"00b41463",
00000248 => x"fe956ae3",
00000249 => x"02c12083",
00000250 => x"02812403",
00000251 => x"02412483",
00000252 => x"02012903",
00000253 => x"01c12983",
00000254 => x"03010113",
00000255 => x"00008067",
00000256 => x"01c99913",
00000257 => x"00445413",
00000258 => x"00896433",
00000259 => x"00040a63",
00000260 => x"00040863",
00000261 => x"fff40413",
00000262 => x"00000013",
00000263 => x"ff1ff06f",
00000264 => x"fc5ff06f",
00000265 => x"00000000",
00000266 => x"00000000",
00000267 => x"00000000",
00000268 => x"fc010113",
00000269 => x"02112e23",
00000270 => x"02512c23",
00000271 => x"02612a23",
00000272 => x"02712823",
00000273 => x"02a12623",
00000274 => x"02b12423",
00000275 => x"02c12223",
00000276 => x"02d12023",
00000277 => x"00e12e23",
00000278 => x"00f12c23",
00000279 => x"01012a23",
00000280 => x"01112823",
00000281 => x"01c12623",
00000282 => x"01d12423",
00000283 => x"01e12223",
00000284 => x"01f12023",
00000285 => x"34102773",
00000286 => x"34071073",
00000287 => x"342027f3",
00000288 => x"0807c863",
00000289 => x"00071683",
00000290 => x"00300593",
00000291 => x"0036f693",
00000292 => x"00270613",
00000293 => x"00b69463",
00000294 => x"00470613",
00000295 => x"34161073",
00000296 => x"00b00713",
00000297 => x"04f77a63",
00000298 => x"6ac00793",
00000299 => x"000780e7",
00000300 => x"03c12083",
00000301 => x"03812283",
00000302 => x"03412303",
00000303 => x"03012383",
00000304 => x"02c12503",
00000305 => x"02812583",
00000306 => x"02412603",
00000307 => x"02012683",
00000308 => x"01c12703",
00000309 => x"01812783",
00000310 => x"01412803",
00000311 => x"01012883",
00000312 => x"00c12e03",
00000313 => x"00812e83",
00000314 => x"00412f03",
00000315 => x"00012f83",
00000316 => x"04010113",
00000317 => x"30200073",
00000318 => x"00001737",
00000319 => x"00279793",
00000320 => x"ae470713",
00000321 => x"00e787b3",
00000322 => x"0007a783",
00000323 => x"00078067",
00000324 => x"80000737",
00000325 => x"ffd74713",
00000326 => x"00e787b3",
00000327 => x"01c00713",
00000328 => x"f8f764e3",
00000329 => x"00001737",
00000330 => x"00279793",
00000331 => x"b1470713",
00000332 => x"00e787b3",
00000333 => x"0007a783",
00000334 => x"00078067",
00000335 => x"800007b7",
00000336 => x"0007a783",
00000337 => x"f69ff06f",
00000338 => x"800007b7",
00000339 => x"0047a783",
00000340 => x"f5dff06f",
00000341 => x"800007b7",
00000342 => x"0087a783",
00000343 => x"f51ff06f",
00000344 => x"800007b7",
00000345 => x"00c7a783",
00000346 => x"f45ff06f",
00000347 => x"8101a783",
00000348 => x"f3dff06f",
00000349 => x"8141a783",
00000350 => x"f35ff06f",
00000351 => x"8181a783",
00000352 => x"f2dff06f",
00000353 => x"81c1a783",
00000354 => x"f25ff06f",
00000355 => x"8201a783",
00000356 => x"f1dff06f",
00000357 => x"8241a783",
00000358 => x"f15ff06f",
00000359 => x"8281a783",
00000360 => x"f0dff06f",
00000361 => x"82c1a783",
00000362 => x"f05ff06f",
00000363 => x"8301a783",
00000364 => x"efdff06f",
00000365 => x"8341a783",
00000366 => x"ef5ff06f",
00000367 => x"8381a783",
00000368 => x"eedff06f",
00000369 => x"83c1a783",
00000370 => x"ee5ff06f",
00000371 => x"8401a783",
00000372 => x"eddff06f",
00000373 => x"8441a783",
00000374 => x"ed5ff06f",
00000375 => x"8481a783",
00000376 => x"ecdff06f",
00000377 => x"84c1a783",
00000378 => x"ec5ff06f",
00000379 => x"8501a783",
00000380 => x"ebdff06f",
00000381 => x"8541a783",
00000382 => x"eb5ff06f",
00000383 => x"8581a783",
00000384 => x"eadff06f",
00000385 => x"85c1a783",
00000386 => x"ea5ff06f",
00000387 => x"8601a783",
00000388 => x"e9dff06f",
00000389 => x"8641a783",
00000390 => x"e95ff06f",
00000391 => x"8681a783",
00000392 => x"e8dff06f",
00000393 => x"86c1a783",
00000394 => x"e85ff06f",
00000395 => x"8701a783",
00000396 => x"e7dff06f",
00000397 => x"00000000",
00000398 => x"00000000",
00000399 => x"fe010113",
00000400 => x"01212823",
00000401 => x"00050913",
00000402 => x"00001537",
00000403 => x"00912a23",
00000404 => x"b8850513",
00000405 => x"000014b7",
00000406 => x"00812c23",
00000407 => x"01312623",
00000408 => x"00112e23",
00000409 => x"01c00413",
00000410 => x"c7dff0ef",
00000411 => x"d7c48493",
00000412 => x"ffc00993",
00000413 => x"008957b3",
00000414 => x"00f7f793",
00000415 => x"00f487b3",
00000416 => x"0007c503",
00000417 => x"ffc40413",
00000418 => x"c45ff0ef",
00000419 => x"ff3414e3",
00000420 => x"01c12083",
00000421 => x"01812403",
00000422 => x"01412483",
00000423 => x"01012903",
00000424 => x"00c12983",
00000425 => x"02010113",
00000426 => x"00008067",
00000427 => x"ff010113",
00000428 => x"00112623",
00000429 => x"00812423",
00000430 => x"00912223",
00000431 => x"b55ff0ef",
00000432 => x"1c050863",
00000433 => x"00001537",
00000434 => x"b8c50513",
00000435 => x"c19ff0ef",
00000436 => x"34202473",
00000437 => x"00900713",
00000438 => x"00f47793",
00000439 => x"03078493",
00000440 => x"00f77463",
00000441 => x"05778493",
00000442 => x"00b00793",
00000443 => x"0087ee63",
00000444 => x"00001737",
00000445 => x"00241793",
00000446 => x"d4c70713",
00000447 => x"00e787b3",
00000448 => x"0007a783",
00000449 => x"00078067",
00000450 => x"800007b7",
00000451 => x"00b78713",
00000452 => x"14e40e63",
00000453 => x"02876a63",
00000454 => x"00378713",
00000455 => x"12e40c63",
00000456 => x"00778793",
00000457 => x"12f40e63",
00000458 => x"00001537",
00000459 => x"cec50513",
00000460 => x"bb5ff0ef",
00000461 => x"00040513",
00000462 => x"f05ff0ef",
00000463 => x"00100793",
00000464 => x"08f40c63",
00000465 => x"0280006f",
00000466 => x"ff07c793",
00000467 => x"00f407b3",
00000468 => x"00f00713",
00000469 => x"fcf76ae3",
00000470 => x"00001537",
00000471 => x"cdc50513",
00000472 => x"b85ff0ef",
00000473 => x"00048513",
00000474 => x"b65ff0ef",
00000475 => x"ffd47413",
00000476 => x"00500793",
00000477 => x"06f40263",
00000478 => x"00001537",
00000479 => x"d3050513",
00000480 => x"b65ff0ef",
00000481 => x"34002573",
00000482 => x"eb5ff0ef",
00000483 => x"00001537",
00000484 => x"d3850513",
00000485 => x"b51ff0ef",
00000486 => x"34302573",
00000487 => x"ea1ff0ef",
00000488 => x"00812403",
00000489 => x"00c12083",
00000490 => x"00412483",
00000491 => x"00001537",
00000492 => x"d4450513",
00000493 => x"01010113",
00000494 => x"b2dff06f",
00000495 => x"00001537",
00000496 => x"b9450513",
00000497 => x"b21ff0ef",
00000498 => x"fb1ff06f",
00000499 => x"00001537",
00000500 => x"bb450513",
00000501 => x"b11ff0ef",
00000502 => x"f7c02783",
00000503 => x"0a07d463",
00000504 => x"0017f793",
00000505 => x"08078a63",
00000506 => x"00001537",
00000507 => x"d0450513",
00000508 => x"fd5ff06f",
00000509 => x"00001537",
00000510 => x"bd050513",
00000511 => x"fc9ff06f",
00000512 => x"00001537",
00000513 => x"be450513",
00000514 => x"fbdff06f",
00000515 => x"00001537",
00000516 => x"bf050513",
00000517 => x"fb1ff06f",
00000518 => x"00001537",
00000519 => x"c0850513",
00000520 => x"fb5ff06f",
00000521 => x"00001537",
00000522 => x"c1c50513",
00000523 => x"f99ff06f",
00000524 => x"00001537",
00000525 => x"c3850513",
00000526 => x"f9dff06f",
00000527 => x"00001537",
00000528 => x"c4c50513",
00000529 => x"f81ff06f",
00000530 => x"00001537",
00000531 => x"c6c50513",
00000532 => x"f75ff06f",
00000533 => x"00001537",
00000534 => x"c8c50513",
00000535 => x"f69ff06f",
00000536 => x"00001537",
00000537 => x"ca850513",
00000538 => x"f5dff06f",
00000539 => x"00001537",
00000540 => x"cc050513",
00000541 => x"f51ff06f",
00000542 => x"00001537",
00000543 => x"d1450513",
00000544 => x"f45ff06f",
00000545 => x"00001537",
00000546 => x"d2450513",
00000547 => x"f39ff06f",
00000548 => x"00c12083",
00000549 => x"00812403",
00000550 => x"00412483",
00000551 => x"01010113",
00000552 => x"00008067",
00000553 => x"01f00793",
00000554 => x"02a7e263",
00000555 => x"800007b7",
00000556 => x"00078793",
00000557 => x"00251513",
00000558 => x"00a78533",
00000559 => x"6ac00793",
00000560 => x"00f52023",
00000561 => x"00000513",
00000562 => x"00008067",
00000563 => x"00100513",
00000564 => x"00008067",
00000565 => x"ff010113",
00000566 => x"00112623",
00000567 => x"00812423",
00000568 => x"00912223",
00000569 => x"43000793",
00000570 => x"30579073",
00000571 => x"00000413",
00000572 => x"01d00493",
00000573 => x"00040513",
00000574 => x"00140413",
00000575 => x"0ff47413",
00000576 => x"fa5ff0ef",
00000577 => x"fe9418e3",
00000578 => x"00c12083",
00000579 => x"00812403",
00000580 => x"00412483",
00000581 => x"01010113",
00000582 => x"00008067",
00000583 => x"fe802503",
00000584 => x"01055513",
00000585 => x"00157513",
00000586 => x"00008067",
00000587 => x"fc000793",
00000588 => x"00a7a423",
00000589 => x"00b7a623",
00000590 => x"00008067",
00000591 => x"00050613",
00000592 => x"00000513",
00000593 => x"0015f693",
00000594 => x"00068463",
00000595 => x"00c50533",
00000596 => x"0015d593",
00000597 => x"00161613",
00000598 => x"fe0596e3",
00000599 => x"00008067",
00000600 => x"00050313",
00000601 => x"ff010113",
00000602 => x"00060513",
00000603 => x"00068893",
00000604 => x"00112623",
00000605 => x"00030613",
00000606 => x"00050693",
00000607 => x"00000713",
00000608 => x"00000793",
00000609 => x"00000813",
00000610 => x"0016fe13",
00000611 => x"00171e93",
00000612 => x"000e0c63",
00000613 => x"01060e33",
00000614 => x"010e3833",
00000615 => x"00e787b3",
00000616 => x"00f807b3",
00000617 => x"000e0813",
00000618 => x"01f65713",
00000619 => x"0016d693",
00000620 => x"00eee733",
00000621 => x"00161613",
00000622 => x"fc0698e3",
00000623 => x"00058663",
00000624 => x"f7dff0ef",
00000625 => x"00a787b3",
00000626 => x"00088a63",
00000627 => x"00030513",
00000628 => x"00088593",
00000629 => x"f69ff0ef",
00000630 => x"00f507b3",
00000631 => x"00c12083",
00000632 => x"00080513",
00000633 => x"00078593",
00000634 => x"01010113",
00000635 => x"00008067",
00000636 => x"06054063",
00000637 => x"0605c663",
00000638 => x"00058613",
00000639 => x"00050593",
00000640 => x"fff00513",
00000641 => x"02060c63",
00000642 => x"00100693",
00000643 => x"00b67a63",
00000644 => x"00c05863",
00000645 => x"00161613",
00000646 => x"00169693",
00000647 => x"feb66ae3",
00000648 => x"00000513",
00000649 => x"00c5e663",
00000650 => x"40c585b3",
00000651 => x"00d56533",
00000652 => x"0016d693",
00000653 => x"00165613",
00000654 => x"fe0696e3",
00000655 => x"00008067",
00000656 => x"00008293",
00000657 => x"fb5ff0ef",
00000658 => x"00058513",
00000659 => x"00028067",
00000660 => x"40a00533",
00000661 => x"00b04863",
00000662 => x"40b005b3",
00000663 => x"f9dff06f",
00000664 => x"40b005b3",
00000665 => x"00008293",
00000666 => x"f91ff0ef",
00000667 => x"40a00533",
00000668 => x"00028067",
00000669 => x"00008293",
00000670 => x"0005ca63",
00000671 => x"00054c63",
00000672 => x"f79ff0ef",
00000673 => x"00058513",
00000674 => x"00028067",
00000675 => x"40b005b3",
00000676 => x"fe0558e3",
00000677 => x"40a00533",
00000678 => x"f61ff0ef",
00000679 => x"40b00533",
00000680 => x"00028067",
00000681 => x"6f727245",
00000682 => x"4e202172",
00000683 => x"5047206f",
00000684 => x"75204f49",
00000685 => x"2074696e",
00000686 => x"746e7973",
00000687 => x"69736568",
00000688 => x"2164657a",
00000689 => x"0000000a",
00000690 => x"6e696c42",
00000691 => x"676e696b",
00000692 => x"44454c20",
00000693 => x"6d656420",
00000694 => x"7270206f",
00000695 => x"6172676f",
00000696 => x"00000a6d",
00000697 => x"0000053c",
00000698 => x"00000548",
00000699 => x"00000554",
00000700 => x"00000560",
00000701 => x"0000056c",
00000702 => x"00000574",
00000703 => x"0000057c",
00000704 => x"00000584",
00000705 => x"0000058c",
00000706 => x"000004a8",
00000707 => x"000004a8",
00000708 => x"00000594",
00000709 => x"0000059c",
00000710 => x"000004a8",
00000711 => x"000004a8",
00000712 => x"000004a8",
00000713 => x"000005a4",
00000714 => x"000004a8",
00000715 => x"000004a8",
00000716 => x"000004a8",
00000717 => x"000005ac",
00000718 => x"000004a8",
00000719 => x"000004a8",
00000720 => x"000004a8",
00000721 => x"000004a8",
00000722 => x"000005b4",
00000723 => x"000005bc",
00000724 => x"000005c4",
00000725 => x"000005cc",
00000726 => x"000005d4",
00000727 => x"000005dc",
00000728 => x"000005e4",
00000729 => x"000005ec",
00000730 => x"000005f4",
00000731 => x"000005fc",
00000732 => x"00000604",
00000733 => x"0000060c",
00000734 => x"00000614",
00000735 => x"0000061c",
00000736 => x"00000624",
00000737 => x"0000062c",
00000738 => x"00007830",
00000739 => x"4554523c",
00000740 => x"0000203e",
00000741 => x"74736e49",
00000742 => x"74637572",
00000743 => x"206e6f69",
00000744 => x"72646461",
00000745 => x"20737365",
00000746 => x"6173696d",
00000747 => x"6e67696c",
00000748 => x"00006465",
00000749 => x"74736e49",
00000750 => x"74637572",
00000751 => x"206e6f69",
00000752 => x"65636361",
00000753 => x"66207373",
00000754 => x"746c7561",
00000755 => x"00000000",
00000756 => x"656c6c49",
00000757 => x"206c6167",
00000758 => x"74736e69",
00000759 => x"74637572",
00000760 => x"006e6f69",
00000761 => x"61657242",
00000762 => x"696f706b",
00000763 => x"0000746e",
00000764 => x"64616f4c",
00000765 => x"64646120",
00000766 => x"73736572",
00000767 => x"73696d20",
00000768 => x"67696c61",
00000769 => x"0064656e",
00000770 => x"64616f4c",
00000771 => x"63636120",
00000772 => x"20737365",
00000773 => x"6c756166",
00000774 => x"00000074",
00000775 => x"726f7453",
00000776 => x"64612065",
00000777 => x"73657264",
00000778 => x"696d2073",
00000779 => x"696c6173",
00000780 => x"64656e67",
00000781 => x"00000000",
00000782 => x"726f7453",
00000783 => x"63612065",
00000784 => x"73736563",
00000785 => x"75616620",
00000786 => x"0000746c",
00000787 => x"69766e45",
00000788 => x"6d6e6f72",
00000789 => x"20746e65",
00000790 => x"6c6c6163",
00000791 => x"6f726620",
00000792 => x"2d55206d",
00000793 => x"65646f6d",
00000794 => x"00000000",
00000795 => x"69766e45",
00000796 => x"6d6e6f72",
00000797 => x"20746e65",
00000798 => x"6c6c6163",
00000799 => x"6f726620",
00000800 => x"2d4d206d",
00000801 => x"65646f6d",
00000802 => x"00000000",
00000803 => x"6863614d",
00000804 => x"20656e69",
00000805 => x"74666f73",
00000806 => x"65726177",
00000807 => x"746e6920",
00000808 => x"75727265",
00000809 => x"00007470",
00000810 => x"6863614d",
00000811 => x"20656e69",
00000812 => x"656d6974",
00000813 => x"6e692072",
00000814 => x"72726574",
00000815 => x"00747075",
00000816 => x"6863614d",
00000817 => x"20656e69",
00000818 => x"65747865",
00000819 => x"6c616e72",
00000820 => x"746e6920",
00000821 => x"75727265",
00000822 => x"00007470",
00000823 => x"74736146",
00000824 => x"746e6920",
00000825 => x"75727265",
00000826 => x"00207470",
00000827 => x"6e6b6e55",
00000828 => x"206e776f",
00000829 => x"70617274",
00000830 => x"75616320",
00000831 => x"203a6573",
00000832 => x"00000000",
00000833 => x"49545b20",
00000834 => x"554f454d",
00000835 => x"52455f54",
00000836 => x"00005d52",
00000837 => x"45445b20",
00000838 => x"45434956",
00000839 => x"5252455f",
00000840 => x"0000005d",
00000841 => x"4d505b20",
00000842 => x"52455f50",
00000843 => x"00005d52",
00000844 => x"50204020",
00000845 => x"00003d43",
00000846 => x"544d202c",
00000847 => x"3d4c4156",
00000848 => x"00000000",
00000849 => x"522f3c20",
00000850 => x"003e4554",
00000851 => x"000007bc",
00000852 => x"000007cc",
00000853 => x"000007f4",
00000854 => x"00000800",
00000855 => x"0000080c",
00000856 => x"00000818",
00000857 => x"00000824",
00000858 => x"00000830",
00000859 => x"0000083c",
00000860 => x"00000728",
00000861 => x"00000728",
00000862 => x"00000848",
00000863 => x"33323130",
00000864 => x"37363534",
00000865 => x"42413938",
00000866 => x"46454443"
);
end neorv32_application_image;

View File

@ -0,0 +1,106 @@
-- #################################################################################################
-- # << NEORV32 - Processor-internal bootloader ROM (BOOTROM) >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2020, 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;
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
rden_i : in std_ulogic; -- read enable
addr_i : in std_ulogic_vector(31 downto 0); -- address
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic -- transfer acknowledge
);
end neorv32_boot_rom;
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
-- local signals --
signal acc_en : std_ulogic;
signal rden : std_ulogic;
signal rdata : std_ulogic_vector(31 downto 0);
signal addr : std_ulogic_vector(boot_rom_size_index_c-1 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);
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 (addr_i(hi_abb_c downto lo_abb_c) = BOOTROM_BASE(hi_abb_c downto lo_abb_c)) else '0';
addr <= addr_i(boot_rom_size_index_c+1 downto 2); -- word aligned
-- Memory Access --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_file_access: process(clk_i)
begin
if rising_edge(clk_i) then
rden <= rden_i and acc_en;
if (acc_en = '1') then -- reduce switching activity when not accessed
rdata <= mem_rom(to_integer(unsigned(addr)));
end if;
end if;
end process mem_file_access;
-- output gate --
data_o <= rdata when (rden = '1') else (others => '0');
ack_o <= rden;
end neorv32_boot_rom_rtl;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,180 @@
-- #################################################################################################
-- # << 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 #
-- # conditions the BUS KEEPER asserts the error signal to inform the CPU. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 (
-- host access --
clk_i : in std_ulogic; -- global clock line
rstn_i : in std_ulogic; -- global reset, low-active, async
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
err_o : out std_ulogic; -- transfer error
-- bus monitoring --
bus_addr_i : in std_ulogic_vector(31 downto 0); -- address
bus_rden_i : in std_ulogic; -- read enable
bus_wren_i : in std_ulogic; -- write enable
bus_ack_i : in std_ulogic; -- transfer acknowledge from bus system
bus_err_i : in std_ulogic; -- transfer error from bus system
bus_tmo_i : in std_ulogic; -- transfer timeout (external interface)
bus_ext_i : in std_ulogic -- external bus access
);
end neorv32_bus_keeper;
architecture neorv32_bus_keeper_rtl of neorv32_bus_keeper 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(buskeeper_size_c); -- low address boundary bit
-- Control register --
constant ctrl_err_type_c : natural := 0; -- r/-: error type: 0=device error, 1=access timeout
constant ctrl_err_flag_c : natural := 31; -- r/c: bus error encountered, sticky; cleared by writing zero
-- sticky error flags --
signal err_flag : std_ulogic;
signal err_type : std_ulogic;
-- access control --
signal acc_en : std_ulogic; -- module access enable
signal wren : std_ulogic; -- word write enable
signal rden : std_ulogic; -- read enable
-- controller --
type control_t is record
pending : std_ulogic;
timeout : std_ulogic_vector(index_size_f(max_proc_int_response_time_c) downto 0);
err_type : std_ulogic;
bus_err : std_ulogic;
end record;
signal control : control_t;
begin
-- Sanity Check --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (max_proc_int_response_time_c < 2) report "NEORV32 PROCESSOR CONFIG ERROR! Processor-internal bus timeout <max_proc_int_response_time_c> has to >= 2." severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = buskeeper_base_c(hi_abb_c downto lo_abb_c)) else '0';
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- bus handshake --
ack_o <= wren or rden;
-- read access --
data_o <= (others => '0');
if (rden = '1') then
data_o(ctrl_err_type_c) <= err_type;
data_o(ctrl_err_flag_c) <= err_flag;
end if;
--
if (control.bus_err = '1') then -- sticky error flag
err_flag <= '1';
err_type <= control.err_type;
elsif ((wren or rden) = '1') then -- clear on or read or write
err_flag <= '0';
err_type <= '0';
end if;
end if;
end process rw_access;
-- Keeper ---------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
keeper_control: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
control.pending <= '0';
control.bus_err <= '0';
control.err_type <= def_rst_val_c;
control.timeout <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
-- defaults --
control.bus_err <= '0';
-- access monitor: IDLE --
if (control.pending = '0') then
control.timeout <= std_ulogic_vector(to_unsigned(max_proc_int_response_time_c, index_size_f(max_proc_int_response_time_c)+1));
if (bus_rden_i = '1') or (bus_wren_i = '1') then
control.pending <= '1';
end if;
-- access monitor: PENDING --
else
control.timeout <= std_ulogic_vector(unsigned(control.timeout) - 1); -- countdown timer
if (bus_err_i = '1') then -- error termination by bus system
control.err_type <= '0'; -- device error
control.bus_err <= '1';
control.pending <= '0';
elsif ((or_reduce_f(control.timeout) = '0') and (bus_ext_i = '0')) or -- internal access timeout
(bus_tmo_i = '1') then -- external access timeout
control.err_type <= '1'; -- timeout error
control.bus_err <= '1';
control.pending <= '0';
elsif (bus_ack_i = '1') then -- normal termination by bus system
control.err_type <= '0'; -- don't care
control.bus_err <= '0';
control.pending <= '0';
end if;
end if;
end if;
end process keeper_control;
-- signal bus error to CPU --
err_o <= control.bus_err;
end neorv32_bus_keeper_rtl;

View File

@ -0,0 +1,273 @@
-- #################################################################################################
-- # << NEORV32 - Bus Switch >> #
-- # ********************************************************************************************* #
-- # Allows to access a single peripheral bus ("p_bus") by two controller busses. Controller port #
-- # A ("ca_bus") has priority over controller port B ("cb_bus"). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_CA_READ_ONLY : boolean; -- set if controller port A is read-only
PORT_CB_READ_ONLY : boolean -- set if controller port B is read-only
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
-- controller interface a --
ca_bus_addr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
ca_bus_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
ca_bus_wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
ca_bus_ben_i : in std_ulogic_vector(03 downto 0); -- byte enable
ca_bus_we_i : in std_ulogic; -- write enable
ca_bus_re_i : in std_ulogic; -- read enable
ca_bus_lock_i : in std_ulogic; -- exclusive access request
ca_bus_ack_o : out std_ulogic; -- bus transfer acknowledge
ca_bus_err_o : out std_ulogic; -- bus transfer error
-- controller interface b --
cb_bus_addr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
cb_bus_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
cb_bus_wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
cb_bus_ben_i : in std_ulogic_vector(03 downto 0); -- byte enable
cb_bus_we_i : in std_ulogic; -- write enable
cb_bus_re_i : in std_ulogic; -- read enable
cb_bus_lock_i : in std_ulogic; -- exclusive access request
cb_bus_ack_o : out std_ulogic; -- bus transfer acknowledge
cb_bus_err_o : out std_ulogic; -- bus transfer error
-- peripheral bus --
p_bus_src_o : out std_ulogic; -- access source: 0 = A, 1 = B
p_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
p_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
p_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
p_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
p_bus_we_o : out std_ulogic; -- write enable
p_bus_re_o : out std_ulogic; -- read enable
p_bus_lock_o : out std_ulogic; -- exclusive access request
p_bus_ack_i : in std_ulogic; -- bus transfer acknowledge
p_bus_err_i : in std_ulogic -- bus transfer error
);
end neorv32_busswitch;
architecture neorv32_busswitch_rtl of neorv32_busswitch is
-- access requests --
signal ca_rd_req_buf, ca_wr_req_buf : std_ulogic;
signal cb_rd_req_buf, cb_wr_req_buf : std_ulogic;
signal ca_req_current, ca_req_buffered : std_ulogic;
signal cb_req_current, cb_req_buffered : std_ulogic;
-- internal bus lines --
signal ca_bus_ack, cb_bus_ack : std_ulogic;
signal ca_bus_err, cb_bus_err : std_ulogic;
signal p_bus_we, p_bus_re : std_ulogic;
-- access arbiter --
type arbiter_state_t is (IDLE, BUSY, RETIRE, BUSY_SWITCHED, RETIRE_SWITCHED);
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 Buffer --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
access_buffer: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
ca_rd_req_buf <= '0';
ca_wr_req_buf <= '0';
cb_rd_req_buf <= '0';
cb_wr_req_buf <= '0';
elsif rising_edge(clk_i) then
-- controller A requests --
if (ca_rd_req_buf = '0') and (ca_wr_req_buf = '0') then -- idle
ca_rd_req_buf <= ca_bus_re_i;
ca_wr_req_buf <= ca_bus_we_i;
elsif (ca_bus_err = '1') or -- error termination
(ca_bus_ack = '1') then -- normal termination
ca_rd_req_buf <= '0';
ca_wr_req_buf <= '0';
end if;
-- controller B requests --
if (cb_rd_req_buf = '0') and (cb_wr_req_buf = '0') then
cb_rd_req_buf <= cb_bus_re_i;
cb_wr_req_buf <= cb_bus_we_i;
elsif (cb_bus_err = '1') or -- error termination
(cb_bus_ack = '1') then -- normal termination
cb_rd_req_buf <= '0';
cb_wr_req_buf <= '0';
end if;
end if;
end process access_buffer;
-- any current requests? --
ca_req_current <= (ca_bus_re_i or ca_bus_we_i) when (PORT_CA_READ_ONLY = false) else ca_bus_re_i;
cb_req_current <= (cb_bus_re_i or cb_bus_we_i) when (PORT_CB_READ_ONLY = false) else cb_bus_re_i;
-- any buffered requests? --
ca_req_buffered <= (ca_rd_req_buf or ca_wr_req_buf) when (PORT_CA_READ_ONLY = false) else ca_rd_req_buf;
cb_req_buffered <= (cb_rd_req_buf or cb_wr_req_buf) when (PORT_CB_READ_ONLY = false) else cb_rd_req_buf;
-- Access Arbiter Sync --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
arbiter_sync: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
arbiter.state <= IDLE;
elsif rising_edge(clk_i) then
arbiter.state <= arbiter.state_nxt;
end if;
end process arbiter_sync;
-- Peripheral Bus Arbiter -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
arbiter_comb: process(arbiter, ca_req_current, cb_req_current, ca_req_buffered, cb_req_buffered,
ca_rd_req_buf, ca_wr_req_buf, cb_rd_req_buf, cb_wr_req_buf, p_bus_ack_i, p_bus_err_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 => -- Controller a has full bus access
-- ------------------------------------------------------------
p_bus_src_o <= '0'; -- access from port A
if (ca_req_current = '1') then -- current request?
arbiter.bus_sel <= '0';
arbiter.state_nxt <= BUSY;
elsif (ca_req_buffered = '1') then -- buffered request?
arbiter.bus_sel <= '0';
arbiter.state_nxt <= RETIRE;
elsif (cb_req_current = '1') then -- current request from controller b?
arbiter.bus_sel <= '1';
arbiter.state_nxt <= BUSY_SWITCHED;
elsif (cb_req_buffered = '1') then -- buffered request from controller b?
arbiter.bus_sel <= '1';
arbiter.state_nxt <= RETIRE_SWITCHED;
end if;
when BUSY => -- transaction in progress
-- ------------------------------------------------------------
p_bus_src_o <= '0'; -- access from port A
arbiter.bus_sel <= '0';
if (p_bus_err_i = '1') or -- error termination
(p_bus_ack_i = '1') then -- normal termination
arbiter.state_nxt <= IDLE;
end if;
when RETIRE => -- retire pending access
-- ------------------------------------------------------------
p_bus_src_o <= '0'; -- access from port A
arbiter.bus_sel <= '0';
if (PORT_CA_READ_ONLY = false) then
arbiter.we_trig <= ca_wr_req_buf;
end if;
arbiter.re_trig <= ca_rd_req_buf;
arbiter.state_nxt <= BUSY;
when BUSY_SWITCHED => -- switched transaction in progress
-- ------------------------------------------------------------
p_bus_src_o <= '1'; -- access from port B
arbiter.bus_sel <= '1';
if (p_bus_err_i = '1') or -- error termination
(p_bus_ack_i = '1') then -- normal termination
if (ca_req_buffered = '1') or (ca_req_current = '1') then -- any request from A?
arbiter.state_nxt <= RETIRE;
else
arbiter.state_nxt <= IDLE;
end if;
end if;
when RETIRE_SWITCHED => -- retire pending switched access
-- ------------------------------------------------------------
p_bus_src_o <= '1'; -- access from port B
arbiter.bus_sel <= '1';
if (PORT_CB_READ_ONLY = false) then
arbiter.we_trig <= cb_wr_req_buf;
end if;
arbiter.re_trig <= cb_rd_req_buf;
arbiter.state_nxt <= BUSY_SWITCHED;
end case;
end process arbiter_comb;
-- Peripheral Bus Switch ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
p_bus_addr_o <= ca_bus_addr_i when (arbiter.bus_sel = '0') else cb_bus_addr_i;
p_bus_wdata_o <= cb_bus_wdata_i when (PORT_CA_READ_ONLY = true) else ca_bus_wdata_i when (PORT_CB_READ_ONLY = true) else
ca_bus_wdata_i when (arbiter.bus_sel = '0') else cb_bus_wdata_i;
p_bus_ben_o <= cb_bus_ben_i when (PORT_CA_READ_ONLY = true) else ca_bus_ben_i when (PORT_CB_READ_ONLY = true) else
ca_bus_ben_i when (arbiter.bus_sel = '0') else cb_bus_ben_i;
p_bus_we <= ca_bus_we_i when (arbiter.bus_sel = '0') else cb_bus_we_i;
p_bus_re <= ca_bus_re_i when (arbiter.bus_sel = '0') else cb_bus_re_i;
p_bus_we_o <= (p_bus_we or arbiter.we_trig);
p_bus_re_o <= (p_bus_re or arbiter.re_trig);
p_bus_lock_o <= ca_bus_lock_i or cb_bus_lock_i;
ca_bus_rdata_o <= p_bus_rdata_i;
cb_bus_rdata_o <= p_bus_rdata_i;
ca_bus_ack <= p_bus_ack_i and (not arbiter.bus_sel);
cb_bus_ack <= p_bus_ack_i and ( arbiter.bus_sel);
ca_bus_ack_o <= ca_bus_ack;
cb_bus_ack_o <= cb_bus_ack;
ca_bus_err <= p_bus_err_i and (not arbiter.bus_sel);
cb_bus_err <= p_bus_err_i and ( arbiter.bus_sel);
ca_bus_err_o <= ca_bus_err;
cb_bus_err_o <= cb_bus_err;
end neorv32_busswitch_rtl;

View File

@ -0,0 +1,257 @@
-- #################################################################################################
-- # << NEORV32 - Custom Functions Subsystem (CFS) >> #
-- # ********************************************************************************************* #
-- # For tightly-coupled custom co-processors. Provides 32x32-bit memory-mapped registers. #
-- # This is just an "example/illustration template". Modify this file to implement your own #
-- # custom design logic. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_cfs is
generic (
CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic
CFS_IN_SIZE : positive; -- size of CFS input conduit in bits
CFS_OUT_SIZE : positive -- size of CFS output conduit in bits
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
rstn_i : in std_ulogic; -- global reset line, low-active, use as async
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- word write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
err_o : out std_ulogic; -- transfer error
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0); -- "clock" inputs
-- interrupt --
irq_o : out std_ulogic; -- interrupt request
-- custom io (conduits) --
cfs_in_i : in std_ulogic_vector(CFS_IN_SIZE-1 downto 0); -- custom inputs
cfs_out_o : out std_ulogic_vector(CFS_OUT_SIZE-1 downto 0) -- custom outputs
);
end neorv32_cfs;
architecture neorv32_cfs_rtl of neorv32_cfs is
-- IO space: module base address (DO NOT MODIFY!) --
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
signal cfs_reg_rd : cfs_regs_t; -- interface registers for READ accesses
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- These assignments are required to check if the CFS is accessed at all.
-- DO NOT MODIFY this unless you really know what you are doing.
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i; -- full 32-bit word write enable
rden <= acc_en and rden_i; -- the read access is always a full 32-bit word wide; if required, the byte/half-word select/masking is done in the CPU
-- NOTE: Do not modify the CFS base address or the CFS' occupied address space as this might cause access
-- collisions with other modules.
-- This module provides an ERROR signal to signal a faulty access operation to the CPU.
-- It can be used to indicate an invalid access (for example to an unused CFS register address) or to signal
-- a faulty state (like "not operational yet"). The error signal can be checked be checked by the applications
-- "bus access fault" exception handler (provided by the system's BUSKEEPER module).
-- This signal may only be set when the module is actually accessed! Tie to zero if not explicitly used.
err_o <= '0';
-- CFS Generics ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- In its default version, the CFS provides the configuration generics. single generic:
-- CFS_IN_SIZE configures the size (in bits) of the CFS input conduit cfs_in_i
-- CFS_OUT_SIZE configures the size (in bits) of the CFS output conduit cfs_out_o
-- CFS_CONFIG is a blank 32-bit generic. It is intended as a "generic conduit" to propagate custom configuration flags from the top entity down to this entiy.
-- CFS IOs --------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- By default, the CFS provides two IO signals (cfs_in_i and cfs_out_o) that are available at the processor top entity.
-- These are intended as "conduits" to propagate custom signals this entity <=> processor top entity.
cfs_out_o <= (others => '0'); -- not used for this minimal example
-- Reset System ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- The CFS can be reset using the global rstn_i signal. This signal should be used as asynchronous reset and is active-low.
-- Note that rstn_i can be asserted by an external reset and also by a watchdog-cause reset.
--
-- Most default peripheral devices of the NEORV32 do NOT use a dedicated reset at all. Instead, these units are reset by writing ZERO
-- to a specific "control register" located right at the beginning of the device's address space (so this register is cleared at first).
-- The crt0 start-up code write ZERO to every single address in the processor's IO space - including the CFS.
-- Make sure that this clearing does not cause any unintended actions in the CFS.
-- Clock System ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- The processor top unit implements a clock generator providing 8 "derived clocks"
-- Actually, these signals should not be used as direct clock signals, but as *clock enable* signals.
-- clkgen_i is always synchronous to the main system clock (clk_i).
--
-- The following clock divider rates are available:
-- clkgen_i(clk_div2_c) -> MAIN_CLK/2
-- clkgen_i(clk_div4_c) -> MAIN_CLK/4
-- clkgen_i(clk_div8_c) -> MAIN_CLK/8
-- clkgen_i(clk_div64_c) -> MAIN_CLK/64
-- clkgen_i(clk_div128_c) -> MAIN_CLK/128
-- clkgen_i(clk_div1024_c) -> MAIN_CLK/1024
-- clkgen_i(clk_div2048_c) -> MAIN_CLK/2048
-- clkgen_i(clk_div4096_c) -> MAIN_CLK/4096
--
-- For instance, if you want to drive a clock process at MAIN_CLK/8 clock speed you can use the following construct:
--
-- if (rstn_i = '0') then -- async and low-active reset (if required at all)
-- ...
-- elsif rising_edge(clk_i) then -- always use the main clock for all clock processes!
-- if (clkgen_i(clk_div8_c) = '1') then -- the div8 "clock" is actually a clock enable
-- ...
-- end if;
-- end if;
--
-- The clkgen_i input clocks are available when at least one IO/peripheral device (for example the SPI) requires the clocks generated by the
-- clock generator. The CFS can enable the clock generator by itself by setting the clkgen_en_o signal high.
-- The CFS cannot ensure to deactivate the clock generator by setting the clkgen_en_o signal low as other peripherals might still keep the generator activated.
-- Make sure to deactivate the CFS's clkgen_en_o if no clocks are required in here to reduce dynamic power consumption.
clkgen_en_o <= '0'; -- not used for this minimal example
-- Interrupt ------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- The CFS features a single interrupt signal, which is connected to the CPU's "fast interrupt" channel 1.
-- The interrupt is triggered by a one-shot rising edge. After triggering, the interrupt appears as "pending" in the CPU's mie register
-- ready to trigger execution of the according interrupt handler. The interrupt request signal should be triggered
-- whenever an interrupt condition is fulfilled. It is the task of the application to programmer to enable/clear the CFS interrupt
-- using the CPU's mie and mip registers when reuqired.
irq_o <= '0'; -- not used for this minimal example
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Here we are reading/writing from/to the interface registers of the module. Please note that the peripheral/IO
-- modules of the NEORV32 can only be written in full word mode (32-bit). Any other write access (half-word or byte)
-- will trigger a store bus access fault exception.
--
-- The CFS provides up to 32 memory-mapped 32-bit interface register. For instance, these could be used to provide
-- a <control register> for global control of the unit, a <data register> for reading/writing from/to a data FIFO, a <command register>
-- for issuing commands and a <status register> for status information.
--
-- Following the interface protocol, each read or write access has to be acknowledged in the following cycle using the ack_o signal (or even later
-- if the module needs additional time; the maximum latency until an unacknowledged access will trigger a bus exception is defined via the package's
-- global "bus_timeout_c" constant). If no ACK is generated at all, the bus access will time out and cause a bus access fault exception.
-- Host access: Read and write access to the interface registers + bus transfer acknowledge.
-- This example only implements four physical r/w register (the four lowest CF register). The remaining addresses of the CFS are not
-- associated with any writable or readable register - an access to those is simply ignored but still acknowledged.
host_access: process(clk_i)
begin
if rising_edge(clk_i) then -- synchronous interface for reads and writes
-- transfer/access acknowledge --
ack_o <= rden or wren; -- default: required for the CPU to check the CFS is answering a bus read OR write request; all r/w accesses (to any cfs_reg) will succeed
-- ack_o <= rden; -- use this construct if your CFS is read-only
-- ack_o <= wren; -- use this construct if your CFS is write-only
-- ack_o <= ... -- or define the ACK by yourself (example: some registers are read-only, some others can only be written, ...)
-- write access --
if (wren = '1') then -- word-wide write-access only!
if (addr = cfs_reg0_addr_c) then -- make sure to use the internal "addr" signal for the read/write interface
cfs_reg_wr(0) <= data_i; -- for example: control register
end if;
if (addr = cfs_reg1_addr_c) then
cfs_reg_wr(1) <= data_i; -- for example: data in/out fifo
end if;
if (addr = cfs_reg2_addr_c) then
cfs_reg_wr(2) <= data_i; -- for example: command fifo
end if;
if (addr = cfs_reg3_addr_c) then
cfs_reg_wr(3) <= data_i; -- for example: status register
end if;
end if;
-- read access --
data_o <= (others => '0'); -- the output has to be zero if there is no actual read access
if (rden = '1') then -- the read access is always a full 32-bit word wide; if required, the byte/half-word select/masking is done in the CPU
case addr is -- make sure to use the internal 'addr' signal for the read/write interface
when cfs_reg0_addr_c => data_o <= cfs_reg_rd(0);
when cfs_reg1_addr_c => data_o <= cfs_reg_rd(1);
when cfs_reg2_addr_c => data_o <= cfs_reg_rd(2);
when cfs_reg3_addr_c => data_o <= cfs_reg_rd(3);
when others => data_o <= (others => '0'); -- the remaining registers are not implemented and will read as zero
end case;
end if;
end if;
end process host_access;
-- CFS Function Core ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- This is where the actual functionality can be implemented.
-- In this example we are just implementing four r/w registers that invert any value written to them.
cfs_core: process(cfs_reg_wr)
begin
cfs_reg_rd(0) <= not cfs_reg_wr(0); -- just invert the written value
cfs_reg_rd(1) <= not cfs_reg_wr(1);
cfs_reg_rd(2) <= not cfs_reg_wr(2);
cfs_reg_rd(3) <= not cfs_reg_wr(3);
end process cfs_core;
end neorv32_cfs_rtl;

View File

@ -0,0 +1,444 @@
-- #################################################################################################
-- # << NEORV32 - CPU Top Entity >> #
-- # ********************************************************************************************* #
-- # NEORV32 CPU: #
-- # * neorv32_cpu.vhd - CPU top entity #
-- # * neorv32_cpu_alu.vhd - Arithmetic/logic unit #
-- # * neorv32_cpu_cp_bitmanip.vhd - Bit-manipulation co-processor #
-- # * neorv32_cpu_cp_fpu.vhd - Single-precision FPU co-processor #
-- # * neorv32_cpu_cp_muldiv.vhd - Integer multiplier/divider co-processor #
-- # * neorv32_cpu_cp_shifter.vhd - Base ISA shifter unit #
-- # * neorv32_cpu_bus.vhd - Instruction and data bus interface unit #
-- # * neorv32_cpu_control.vhd - CPU control and CSR system #
-- # * neorv32_cpu_decompressor.vhd - Compressed instructions decoder #
-- # * neorv32_cpu_regfile.vhd - Data register file #
-- # * neorv32_package.vhd - Main CPU & Processor package file #
-- # #
-- # Check out the CPU's online documentation for more information: #
-- # HQ: https://github.com/stnolting/neorv32 #
-- # Data Sheet: https://stnolting.github.io/neorv32 #
-- # User Guide: https://stnolting.github.io/neorv32/ug #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_cpu is
generic (
-- General --
HW_THREAD_ID : natural; -- hardware thread id (32-bit)
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0); -- cpu boot address
CPU_DEBUG_ADDR : std_ulogic_vector(31 downto 0); -- cpu debug mode start address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr : boolean; -- implement base counters?
CPU_EXTENSION_RISCV_Zihpm : boolean; -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
CPU_EXTENSION_RISCV_Zmmul : boolean; -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_DEBUG : boolean; -- implement CPU debug mode?
-- Extension Options --
FAST_MUL_EN : boolean; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural; -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES : natural; -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural -- total size of HPM counters (0..64)
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
sleep_o : out std_ulogic; -- cpu is in sleep mode when set
debug_o : out std_ulogic; -- cpu is in debug mode when set
-- instruction bus interface --
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
i_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
i_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
i_bus_we_o : out std_ulogic; -- write enable
i_bus_re_o : out std_ulogic; -- read enable
i_bus_lock_o : out std_ulogic; -- exclusive access request
i_bus_ack_i : in std_ulogic; -- bus transfer acknowledge
i_bus_err_i : in std_ulogic; -- bus transfer error
i_bus_fence_o : out std_ulogic; -- executed FENCEI operation
i_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level
-- data bus interface --
d_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
d_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
d_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
d_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
d_bus_we_o : out std_ulogic; -- write enable
d_bus_re_o : out std_ulogic; -- read enable
d_bus_lock_o : out std_ulogic; -- exclusive access request
d_bus_ack_i : in std_ulogic; -- bus transfer acknowledge
d_bus_err_i : in std_ulogic; -- bus transfer error
d_bus_fence_o : out std_ulogic; -- executed FENCE operation
d_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level
-- system time input from MTIME --
time_i : in std_ulogic_vector(63 downto 0); -- current system time
-- interrupts (risc-v compliant) --
msw_irq_i : in std_ulogic;-- machine software interrupt
mext_irq_i : in std_ulogic;-- machine external interrupt
mtime_irq_i : in std_ulogic;-- machine timer interrupt
-- fast interrupts (custom) --
firq_i : in std_ulogic_vector(15 downto 0);
-- debug mode (halt) request --
db_halt_req_i : in std_ulogic
);
end neorv32_cpu;
architecture neorv32_cpu_rtl of neorv32_cpu is
-- local signals --
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
signal comparator : std_ulogic_vector(1 downto 0); -- comparator result
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu address result
signal mem_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory read data
signal alu_idone : std_ulogic; -- iterative alu operation done
signal bus_i_wait : std_ulogic; -- wait for current bus instruction fetch
signal bus_d_wait : std_ulogic; -- wait for current bus data access
signal csr_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
signal mar : std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register
signal ma_instr : std_ulogic; -- misaligned instruction address
signal ma_load : std_ulogic; -- misaligned load data address
signal ma_store : std_ulogic; -- misaligned store data address
signal excl_state : std_ulogic; -- atomic/exclusive access lock status
signal be_instr : std_ulogic; -- bus error on instruction access
signal be_load : std_ulogic; -- bus error on load data access
signal be_store : std_ulogic; -- bus error on store data access
signal fetch_pc : std_ulogic_vector(data_width_c-1 downto 0); -- pc for instruction fetch
signal curr_pc : std_ulogic_vector(data_width_c-1 downto 0); -- current pc (for current executed instruction)
signal next_pc : std_ulogic_vector(data_width_c-1 downto 0); -- next pc (for next executed instruction)
signal fpu_flags : std_ulogic_vector(4 downto 0); -- FPU exception flags
-- pmp interface --
signal pmp_addr : pmp_addr_if_t;
signal pmp_ctrl : pmp_ctrl_if_t;
begin
-- CPU ISA Configuration ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report
"NEORV32 CPU ISA Configuration (MARCH): " &
cond_sel_string_f(CPU_EXTENSION_RISCV_E, "RV32E", "RV32I") &
cond_sel_string_f(CPU_EXTENSION_RISCV_M, "M", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_A, "A", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_C, "C", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_B, "B", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_U, "U", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zicsr, "_Zicsr", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zicntr, "_Zicntr", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zihpm, "_Zihpm", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zifencei, "_Zifencei", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zfinx, "_Zfinx", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zmmul, "_Zmmul", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_DEBUG, "_Debug", "") &
""
severity note;
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- hardware reset notifier --
assert not (dedicated_reset_c = false) report "NEORV32 CPU CONFIG NOTE: Implementing NO dedicated hardware reset for uncritical registers (default, might reduce area). Set package constant <dedicated_reset_c> = TRUE to configure a DEFINED reset value for all CPU registers." severity note;
assert not (dedicated_reset_c = true) report "NEORV32 CPU CONFIG NOTE: Implementing defined hardware reset for uncritical registers (non-default, reset-to-zero, might increase area)." severity note;
assert not ((def_rst_val_c /= '-') and (def_rst_val_c /= '0')) report "NEORV32 CPU CONFIG ERROR! Invalid configuration of package <def_rst_val_c> constant (has to be '-' or '0')." severity error;
-- CSR system --
assert not (CPU_EXTENSION_RISCV_Zicsr = false) report "NEORV32 CPU CONFIG WARNING! No exception/interrupt/trap/privileged features available when <CPU_EXTENSION_RISCV_Zicsr> = false." severity warning;
-- CPU counters (cycle and instret) --
assert not ((CPU_EXTENSION_RISCV_Zicntr = true) and ((CPU_CNT_WIDTH < 0) or (CPU_CNT_WIDTH > 64))) report "NEORV32 CPU CONFIG ERROR! Invalid <CPU_CNT_WIDTH> configuration. Has to be 0..64." severity error;
assert not ((CPU_EXTENSION_RISCV_Zicntr = true) and (CPU_CNT_WIDTH < 64)) report "NEORV32 CPU CONFIG WARNING! Implementing CPU <cycle> and <instret> CSRs with reduced size (" & integer'image(CPU_CNT_WIDTH) & "-bit instead of 64-bit). This is not RISC-V compliant and might have unintended SW side effects." severity warning;
-- U-extension requires Zicsr extension --
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (CPU_EXTENSION_RISCV_U = true)) report "NEORV32 CPU CONFIG ERROR! User mode requires <CPU_EXTENSION_RISCV_Zicsr> extension to be enabled." severity error;
-- Instruction prefetch buffer size --
assert not (is_power_of_two_f(CPU_IPB_ENTRIES) = false) report "NEORV32 CPU CONFIG ERROR! Number of entries in instruction prefetch buffer <CPU_IPB_ENTRIES> has to be a power of two." severity error;
-- Co-processor timeout counter (for debugging only) --
assert not (cp_timeout_en_c = true) report "NEORV32 CPU CONFIG WARNING! Co-processor timeout counter enabled. This should be used for debugging/simulation only." severity warning;
-- PMP regions check --
assert not (PMP_NUM_REGIONS > 64) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions <PMP_NUM_REGIONS> out of valid range (0..64)." severity error;
-- PMP granularity --
assert not ((is_power_of_two_f(PMP_MIN_GRANULARITY) = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! <PMP_MIN_GRANULARITY> has to be a power of two." severity error;
assert not ((PMP_MIN_GRANULARITY < 8) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! <PMP_MIN_GRANULARITY> has to be >= 8 bytes." severity error;
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! Physical memory protection (PMP) requires <CPU_EXTENSION_RISCV_Zicsr> extension to be enabled." severity error;
-- HPM counters check --
assert not ((CPU_EXTENSION_RISCV_Zihpm = true) and (HPM_NUM_CNTS > 29)) report "NEORV32 CPU CONFIG ERROR! Number of HPM counters <HPM_NUM_CNTS> out of valid range (0..29)." severity error;
assert not ((CPU_EXTENSION_RISCV_Zihpm = true) and ((HPM_CNT_WIDTH < 0) or (HPM_CNT_WIDTH > 64))) report "NEORV32 CPU CONFIG ERROR! HPM counter width <HPM_CNT_WIDTH> has to be 0..64 bit." severity error;
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (CPU_EXTENSION_RISCV_Zihpm = true)) report "NEORV32 CPU CONFIG ERROR! Hardware performance monitors extension <CPU_EXTENSION_RISCV_Zihpm> requires <CPU_EXTENSION_RISCV_Zicsr> extension to be enabled." severity error;
-- Mul-extension --
assert not ((CPU_EXTENSION_RISCV_Zmmul = true) and (CPU_EXTENSION_RISCV_M = true)) report "NEORV32 CPU CONFIG ERROR! <M> and <Zmmul> extensions cannot co-exist!" severity error;
-- Debug mode --
assert not ((CPU_EXTENSION_RISCV_DEBUG = true) and (CPU_EXTENSION_RISCV_Zicsr = false)) report "NEORV32 CPU CONFIG ERROR! Debug mode requires <CPU_EXTENSION_RISCV_Zicsr> extension to be enabled." severity error;
assert not ((CPU_EXTENSION_RISCV_DEBUG = true) and (CPU_EXTENSION_RISCV_Zifencei = false)) report "NEORV32 CPU CONFIG ERROR! Debug mode requires <CPU_EXTENSION_RISCV_Zifencei> extension to be enabled." severity error;
-- fast multiplication option --
assert not (FAST_MUL_EN = true) report "NEORV32 CPU CONFIG NOTE: <FAST_MUL_EN> set. Trying to use DSP blocks for base ISA multiplications." severity note;
-- fast shift option --
assert not (FAST_SHIFT_EN = true) report "NEORV32 CPU CONFIG NOTE: <FAST_SHIFT_EN> set. Implementing full-parallel logic / barrel shifters." severity note;
-- Control Unit ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_control_inst: neorv32_cpu_control
generic map (
-- General --
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id
CPU_BOOT_ADDR => CPU_BOOT_ADDR, -- cpu boot address
CPU_DEBUG_ADDR => CPU_DEBUG_ADDR, -- cpu debug mode start address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr, -- implement base counters?
CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm, -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
CPU_EXTENSION_RISCV_Zmmul => CPU_EXTENSION_RISCV_Zmmul, -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_DEBUG => CPU_EXTENSION_RISCV_DEBUG, -- implement CPU debug mode?
-- Extension Options --
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES => CPU_IPB_ENTRIES, -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH -- total size of HPM counters
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_o => ctrl, -- main control bus
-- status input --
alu_idone_i => alu_idone, -- ALU iterative operation done
bus_i_wait_i => bus_i_wait, -- wait for bus
bus_d_wait_i => bus_d_wait, -- wait for bus
excl_state_i => excl_state, -- atomic/exclusive access lock status
-- data input --
instr_i => instr, -- instruction
cmp_i => comparator, -- comparator status
alu_add_i => alu_add, -- ALU address result
rs1_i => rs1, -- rf source 1
-- data output --
imm_o => imm, -- immediate
fetch_pc_o => fetch_pc, -- PC for instruction fetch
curr_pc_o => curr_pc, -- current PC (corresponding to current instruction)
next_pc_o => next_pc, -- next PC (corresponding to next instruction)
csr_rdata_o => csr_rdata, -- CSR read data
-- FPU interface --
fpu_flags_i => fpu_flags, -- exception flags
-- debug mode (halt) request --
db_halt_req_i => db_halt_req_i,
-- interrupts (risc-v compliant) --
msw_irq_i => msw_irq_i, -- machine software interrupt
mext_irq_i => mext_irq_i, -- machine external interrupt
mtime_irq_i => mtime_irq_i, -- machine timer interrupt
-- fast interrupts (custom) --
firq_i => firq_i, -- fast interrupt trigger
-- system time input from MTIME --
time_i => time_i, -- current system time
-- physical memory protection --
pmp_addr_o => pmp_addr, -- addresses
pmp_ctrl_o => pmp_ctrl, -- configs
-- bus access exceptions --
mar_i => mar, -- memory address register
ma_instr_i => ma_instr, -- misaligned instruction address
ma_load_i => ma_load, -- misaligned load data address
ma_store_i => ma_store, -- misaligned store data address
be_instr_i => be_instr, -- bus error on instruction access
be_load_i => be_load, -- bus error on load data access
be_store_i => be_store -- bus error on store data access
);
-- CPU is sleeping? --
sleep_o <= ctrl(ctrl_sleep_c); -- set when CPU is sleeping (after WFI)
-- CPU is in debug mode? --
debug_o <= ctrl(ctrl_debug_running_c);
-- Register File --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_regfile_inst: neorv32_cpu_regfile
generic map (
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E -- implement embedded RF extension?
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
ctrl_i => ctrl, -- main control bus
-- data input --
mem_i => mem_rdata, -- memory read data
alu_i => alu_res, -- ALU result
-- data output --
rs1_o => rs1, -- operand 1
rs2_o => rs2 -- operand 2
);
-- ALU ------------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_alu_inst: neorv32_cpu_alu
generic map (
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_Zmmul => CPU_EXTENSION_RISCV_Zmmul, -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
-- Extension Options --
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl, -- main control bus
-- data input --
rs1_i => rs1, -- rf source 1
rs2_i => rs2, -- rf source 2
pc_i => curr_pc, -- current PC
pc2_i => next_pc, -- next PC
imm_i => imm, -- immediate
csr_i => csr_rdata, -- CSR read data
-- data output --
cmp_o => comparator, -- comparator status
res_o => alu_res, -- ALU result
add_o => alu_add, -- address computation result
fpu_flags_o => fpu_flags, -- FPU exception flags
-- status --
idone_o => alu_idone -- iterative processing units done?
);
-- Bus Interface Unit ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_bus_inst: neorv32_cpu_bus
generic map (
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl, -- main control bus
-- cpu instruction fetch interface --
fetch_pc_i => fetch_pc, -- PC for instruction fetch
instr_o => instr, -- instruction
i_wait_o => bus_i_wait, -- wait for fetch to complete
--
ma_instr_o => ma_instr, -- misaligned instruction address
be_instr_o => be_instr, -- bus error on instruction access
-- cpu data access interface --
addr_i => alu_add, -- ALU.add result -> access address
wdata_i => rs2, -- write data
rdata_o => mem_rdata, -- read data
mar_o => mar, -- current memory address register
d_wait_o => bus_d_wait, -- wait for access to complete
--
excl_state_o => excl_state, -- atomic/exclusive access status
ma_load_o => ma_load, -- misaligned load data address
ma_store_o => ma_store, -- misaligned store data address
be_load_o => be_load, -- bus error on load data access
be_store_o => be_store, -- bus error on store data access
-- physical memory protection --
pmp_addr_i => pmp_addr, -- addresses
pmp_ctrl_i => pmp_ctrl, -- configurations
-- instruction bus --
i_bus_addr_o => i_bus_addr_o, -- bus access address
i_bus_rdata_i => i_bus_rdata_i, -- bus read data
i_bus_wdata_o => i_bus_wdata_o, -- bus write data
i_bus_ben_o => i_bus_ben_o, -- byte enable
i_bus_we_o => i_bus_we_o, -- write enable
i_bus_re_o => i_bus_re_o, -- read enable
i_bus_lock_o => i_bus_lock_o, -- exclusive access request
i_bus_ack_i => i_bus_ack_i, -- bus transfer acknowledge
i_bus_err_i => i_bus_err_i, -- bus transfer error
i_bus_fence_o => i_bus_fence_o, -- fence operation
-- data bus --
d_bus_addr_o => d_bus_addr_o, -- bus access address
d_bus_rdata_i => d_bus_rdata_i, -- bus read data
d_bus_wdata_o => d_bus_wdata_o, -- bus write data
d_bus_ben_o => d_bus_ben_o, -- byte enable
d_bus_we_o => d_bus_we_o, -- write enable
d_bus_re_o => d_bus_re_o, -- read enable
d_bus_lock_o => d_bus_lock_o, -- exclusive access request
d_bus_ack_i => d_bus_ack_i, -- bus transfer acknowledge
d_bus_err_i => d_bus_err_i, -- bus transfer error
d_bus_fence_o => d_bus_fence_o -- fence operation
);
-- current privilege level --
i_bus_priv_o <= ctrl(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c);
d_bus_priv_o <= ctrl(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c);
end neorv32_cpu_rtl;

View File

@ -0,0 +1,349 @@
-- #################################################################################################
-- # << NEORV32 - Arithmetical/Logical Unit >> #
-- # ********************************************************************************************* #
-- # Main data and address ALU and co-processor interface/arbiter. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_cpu_alu is
generic (
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_B : boolean; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_M : boolean; -- implement mul/div extension?
CPU_EXTENSION_RISCV_Zmmul : boolean; -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
-- Extension Options --
FAST_MUL_EN : boolean; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean -- use barrel shifter for shift operations
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
-- data input --
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- next PC
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
-- data output --
cmp_o : out std_ulogic_vector(1 downto 0); -- comparator status
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
add_o : out std_ulogic_vector(data_width_c-1 downto 0); -- address computation result
fpu_flags_o : out std_ulogic_vector(4 downto 0); -- FPU exception flags
-- status --
idone_o : out std_ulogic -- iterative processing units done?
);
end neorv32_cpu_alu;
architecture neorv32_cpu_cpu_rtl of neorv32_cpu_alu is
-- comparator --
signal cmp_opx : std_ulogic_vector(data_width_c downto 0);
signal cmp_opy : std_ulogic_vector(data_width_c downto 0);
signal cmp : std_ulogic_vector(1 downto 0); -- comparator status
-- operands --
signal opa, opb : std_ulogic_vector(data_width_c-1 downto 0);
-- results --
signal addsub_res : std_ulogic_vector(data_width_c downto 0);
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0);
signal cp_res : std_ulogic_vector(data_width_c-1 downto 0);
-- co-processor arbiter and interface --
type cp_ctrl_t is record
cmd : std_ulogic;
cmd_ff : std_ulogic;
start : std_ulogic;
busy : std_ulogic;
timeout : std_ulogic_vector(9 downto 0);
end record;
signal cp_ctrl : cp_ctrl_t;
-- co-processor interface --
signal cp_start : std_ulogic_vector(3 downto 0); -- trigger co-processor i
signal cp_valid : std_ulogic_vector(3 downto 0); -- co-processor i done
signal cp_result : cp_data_if_t; -- co-processor result
begin
-- Comparator Unit (for conditional branches) ---------------------------------------------
-- -------------------------------------------------------------------------------------------
cmp_opx <= (rs1_i(rs1_i'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs1_i;
cmp_opy <= (rs2_i(rs2_i'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs2_i;
cmp(cmp_equal_c) <= '1' when (rs1_i = rs2_i) else '0';
cmp(cmp_less_c) <= '1' when (signed(cmp_opx) < signed(cmp_opy)) else '0';
cmp_o <= cmp;
-- ALU Input Operand Mux ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
opa <= pc_i when (ctrl_i(ctrl_alu_opa_mux_c) = '1') else rs1_i; -- operand a (first ALU input operand), only required for arithmetic ops
opb <= imm_i when (ctrl_i(ctrl_alu_opb_mux_c) = '1') else rs2_i; -- operand b (second ALU input operand)
-- Binary Adder/Subtracter ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
binary_arithmetic_core: process(ctrl_i, opa, opb)
variable cin_v : std_ulogic_vector(0 downto 0);
variable op_a_v : std_ulogic_vector(data_width_c downto 0);
variable op_b_v : std_ulogic_vector(data_width_c downto 0);
variable op_y_v : std_ulogic_vector(data_width_c downto 0);
variable res_v : std_ulogic_vector(data_width_c downto 0);
begin
-- operand sign-extension --
op_a_v := (opa(opa'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & opa;
op_b_v := (opb(opb'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & opb;
-- add/sub(slt) select --
if (ctrl_i(ctrl_alu_op0_c) = '1') then -- subtraction
op_y_v := not op_b_v;
cin_v(0) := '1';
else -- addition
op_y_v := op_b_v;
cin_v(0) := '0';
end if;
-- adder core --
addsub_res <= std_ulogic_vector(unsigned(op_a_v) + unsigned(op_y_v) + unsigned(cin_v(0 downto 0)));
end process binary_arithmetic_core;
-- direct output of adder result --
add_o <= addsub_res(data_width_c-1 downto 0);
-- ALU Operation Select -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
alu_core: process(ctrl_i, addsub_res, rs1_i, opb)
begin
case ctrl_i(ctrl_alu_op2_c downto ctrl_alu_op0_c) is
when alu_op_add_c => alu_res <= addsub_res(data_width_c-1 downto 0); -- (default)
when alu_op_sub_c => alu_res <= addsub_res(data_width_c-1 downto 0);
-- when alu_op_mova_c => alu_res <= rs1_i; -- FIXME
when alu_op_slt_c => alu_res <= (others => '0'); alu_res(0) <= addsub_res(addsub_res'left); -- => carry/borrow
when alu_op_movb_c => alu_res <= opb;
when alu_op_xor_c => alu_res <= rs1_i xor opb; -- only rs1 required for logic ops (opa would also contain pc)
when alu_op_or_c => alu_res <= rs1_i or opb;
when alu_op_and_c => alu_res <= rs1_i and opb;
when others => alu_res <= addsub_res(data_width_c-1 downto 0);
end case;
end process alu_core;
-- ALU Function Select --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
alu_function_mux: process(ctrl_i, alu_res, pc2_i, csr_i, cp_res)
begin
case ctrl_i(ctrl_alu_func1_c downto ctrl_alu_func0_c) is
when alu_func_core_c => res_o <= alu_res; -- (default)
when alu_func_nxpc_c => res_o <= pc2_i;
when alu_func_csrr_c => res_o <= csr_i;
when alu_func_copro_c => res_o <= cp_res;
when others => res_o <= alu_res; -- undefined
end case;
end process alu_function_mux;
-- **************************************************************************************************************************
-- Co-Processors
-- **************************************************************************************************************************
-- Co-Processor Arbiter -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Interface:
-- Co-processor "valid" signal has to be asserted (for one cycle) one cycle before asserting output data
-- Co-processor "output data" has to be always zero unless co-processor was explicitly triggered
cp_arbiter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
cp_ctrl.cmd_ff <= '0';
cp_ctrl.busy <= '0';
cp_ctrl.timeout <= (others => '0');
elsif rising_edge(clk_i) then
cp_ctrl.cmd_ff <= cp_ctrl.cmd;
-- timeout counter --
if (cp_ctrl.start = '1') then
cp_ctrl.busy <= '1';
elsif (or_reduce_f(cp_valid) = '1') then
cp_ctrl.busy <= '0';
end if;
if (cp_ctrl.busy = '1') and (cp_timeout_en_c = true) then
cp_ctrl.timeout <= std_ulogic_vector(unsigned(cp_ctrl.timeout) + 1);
else
cp_ctrl.timeout <= (others => '0');
end if;
if (cp_ctrl.timeout(cp_ctrl.timeout'left) = '1') and (cp_timeout_en_c = true) then -- timeout
assert false report "NEORV32 CPU CO-PROCESSOR TIMEOUT ERROR!" severity warning;
end if;
end if;
end process cp_arbiter;
-- is co-processor operation? --
cp_ctrl.cmd <= '1' when (ctrl_i(ctrl_alu_func1_c downto ctrl_alu_func0_c) = alu_func_copro_c) else '0';
cp_ctrl.start <= '1' when (cp_ctrl.cmd = '1') and (cp_ctrl.cmd_ff = '0') else '0';
-- co-processor select / star trigger --
cp_start(0) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "00") else '0';
cp_start(1) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "01") else '0';
cp_start(2) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "10") else '0';
cp_start(3) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "11") else '0';
-- co-processor operation done? --
idone_o <= or_reduce_f(cp_valid);
-- co-processor result - only the *actually selected* co-processor may output data != 0 --
cp_res <= cp_result(0) or cp_result(1) or cp_result(2) or cp_result(3);
-- Co-Processor 0: Shifter (CPU Core ISA) --------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_shifter_inst: neorv32_cpu_cp_shifter
generic map (
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(0), -- trigger operation
-- data input --
rs1_i => rs1_i, -- rf source 1
shamt_i => opb(index_size_f(data_width_c)-1 downto 0), -- shift amount
-- result and status --
res_o => cp_result(0), -- operation result
valid_o => cp_valid(0) -- data output valid
);
-- Co-Processor 1: Integer Multiplication/Division ('M' Extension) ------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_muldiv_inst_true:
if (CPU_EXTENSION_RISCV_M = true) or (CPU_EXTENSION_RISCV_Zmmul = true) generate
neorv32_cpu_cp_muldiv_inst: neorv32_cpu_cp_muldiv
generic map (
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for faster multiplication
DIVISION_EN => CPU_EXTENSION_RISCV_M -- implement divider hardware
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(1), -- trigger operation
-- data input --
rs1_i => rs1_i, -- rf source 1
rs2_i => rs2_i, -- rf source 2
-- result and status --
res_o => cp_result(1), -- operation result
valid_o => cp_valid(1) -- data output valid
);
end generate;
neorv32_cpu_cp_muldiv_inst_false:
if (CPU_EXTENSION_RISCV_M = false) and (CPU_EXTENSION_RISCV_Zmmul = false) generate
cp_result(1) <= (others => '0');
cp_valid(1) <= cp_start(1); -- to make sure CPU does not get stalled if there is an accidental access
end generate;
-- Co-Processor 2: Bit-Manipulation Unit ('B' Extension) ----------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_bitmanip_inst_true:
if (CPU_EXTENSION_RISCV_B = true) generate
neorv32_cpu_cp_bitmanip_inst: neorv32_cpu_cp_bitmanip
generic map (
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(2), -- trigger operation
-- data input --
cmp_i => cmp, -- comparator status
rs1_i => rs1_i, -- rf source 1
rs2_i => rs2_i, -- rf source 2
shamt_i => opb(index_size_f(data_width_c)-1 downto 0), -- shift amount
-- result and status --
res_o => cp_result(2), -- operation result
valid_o => cp_valid(2) -- data output valid
);
end generate;
neorv32_cpu_cp_bitmanip_inst_false:
if (CPU_EXTENSION_RISCV_B = false) generate
cp_result(2) <= (others => '0');
cp_valid(2) <= cp_start(2); -- to make sure CPU does not get stalled if there is an accidental access
end generate;
-- Co-Processor 3: Single-Precision Floating-Point Unit ('Zfinx' Extension) ---------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_fpu_inst_true:
if (CPU_EXTENSION_RISCV_Zfinx = true) generate
neorv32_cpu_cp_fpu_inst: neorv32_cpu_cp_fpu
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(3), -- trigger operation
-- data input --
cmp_i => cmp, -- comparator status
rs1_i => rs1_i, -- rf source 1
rs2_i => rs2_i, -- rf source 2
-- result and status --
res_o => cp_result(3), -- operation result
fflags_o => fpu_flags_o, -- exception flags
valid_o => cp_valid(3) -- data output valid
);
end generate;
neorv32_cpu_cp_fpu_inst_false:
if (CPU_EXTENSION_RISCV_Zfinx = false) generate
cp_result(3) <= (others => '0');
fpu_flags_o <= (others => '0');
cp_valid(3) <= cp_start(3); -- to make sure CPU does not get stalled if there is an accidental access
end generate;
end neorv32_cpu_cpu_rtl;

View File

@ -0,0 +1,509 @@
-- #################################################################################################
-- # << NEORV32 - Bus Interface Unit >> #
-- # ********************************************************************************************* #
-- # Instruction and data bus interfaces and physical memory protection (PMP). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_cpu_bus is
generic (
CPU_EXTENSION_RISCV_A : boolean; -- implement atomic extension?
CPU_EXTENSION_RISCV_C : boolean; -- implement compressed extension?
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
-- cpu instruction fetch interface --
fetch_pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
instr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- instruction
i_wait_o : out std_ulogic; -- wait for fetch to complete
--
ma_instr_o : out std_ulogic; -- misaligned instruction address
be_instr_o : out std_ulogic; -- bus error on instruction access
-- cpu data access interface --
addr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result -> access address
wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- write data
rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- read data
mar_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register
d_wait_o : out std_ulogic; -- wait for access to complete
--
excl_state_o : out std_ulogic; -- atomic/exclusive access status
ma_load_o : out std_ulogic; -- misaligned load data address
ma_store_o : out std_ulogic; -- misaligned store data address
be_load_o : out std_ulogic; -- bus error on load data access
be_store_o : out std_ulogic; -- bus error on store data access
-- physical memory protection --
pmp_addr_i : in pmp_addr_if_t; -- addresses
pmp_ctrl_i : in pmp_ctrl_if_t; -- configs
-- instruction bus --
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
i_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
i_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
i_bus_we_o : out std_ulogic; -- write enable
i_bus_re_o : out std_ulogic; -- read enable
i_bus_lock_o : out std_ulogic; -- exclusive access request
i_bus_ack_i : in std_ulogic; -- bus transfer acknowledge
i_bus_err_i : in std_ulogic; -- bus transfer error
i_bus_fence_o : out std_ulogic; -- fence operation
-- data bus --
d_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
d_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
d_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
d_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
d_bus_we_o : out std_ulogic; -- write enable
d_bus_re_o : out std_ulogic; -- read enable
d_bus_lock_o : out std_ulogic; -- exclusive access request
d_bus_ack_i : in std_ulogic; -- bus transfer acknowledge
d_bus_err_i : in std_ulogic; -- bus transfer error
d_bus_fence_o : out std_ulogic -- fence operation
);
end neorv32_cpu_bus;
architecture neorv32_cpu_bus_rtl of neorv32_cpu_bus is
-- PMP modes --
constant pmp_off_mode_c : std_ulogic_vector(1 downto 0) := "00"; -- null region (disabled)
--constant pmp_tor_mode_c : std_ulogic_vector(1 downto 0) := "01"; -- top of range
--constant pmp_na4_mode_c : std_ulogic_vector(1 downto 0) := "10"; -- naturally aligned four-byte region
constant pmp_napot_mode_c : std_ulogic_vector(1 downto 0) := "11"; -- naturally aligned power-of-two region (>= 8 bytes)
-- PMP granularity --
constant pmp_g_c : natural := index_size_f(PMP_MIN_GRANULARITY);
-- PMP configuration register bits --
constant pmp_cfg_r_c : natural := 0; -- read permit
constant pmp_cfg_w_c : natural := 1; -- write permit
constant pmp_cfg_x_c : natural := 2; -- execute permit
constant pmp_cfg_al_c : natural := 3; -- mode bit low
constant pmp_cfg_ah_c : natural := 4; -- mode bit high
--
constant pmp_cfg_l_c : natural := 7; -- locked entry
-- data interface registers --
signal mar, mdo, mdi : std_ulogic_vector(data_width_c-1 downto 0);
-- data access --
signal d_bus_wdata : std_ulogic_vector(data_width_c-1 downto 0); -- write data
signal d_bus_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- read data
signal rdata_align : std_ulogic_vector(data_width_c-1 downto 0); -- read-data alignment
signal d_bus_ben : std_ulogic_vector(3 downto 0); -- write data byte enable
-- misaligned access? --
signal d_misaligned, i_misaligned : std_ulogic;
-- bus arbiter --
type bus_arbiter_t is record
rd_req : std_ulogic; -- read access in progress
wr_req : std_ulogic; -- write access in progress
err_align : std_ulogic; -- alignment error
err_bus : std_ulogic; -- bus access error
end record;
signal i_arbiter, d_arbiter : bus_arbiter_t;
-- atomic/exclusive access - reservation controller --
signal exclusive_lock : std_ulogic;
signal exclusive_lock_status : std_ulogic_vector(data_width_c-1 downto 0); -- read data
-- physical memory protection --
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
type pmp_t is record
addr_mask : pmp_addr_t;
region_base : pmp_addr_t; -- region config base address
region_i_addr : pmp_addr_t; -- masked instruction access base address for comparator
region_d_addr : pmp_addr_t; -- masked data access base address for comparator
i_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for instruction interface
d_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for data interface
if_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for fetch operation
ld_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for load operation
st_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for store operation
end record;
signal pmp : pmp_t;
-- memory control signal buffer (when using PMP) --
signal d_bus_we, d_bus_we_buf : std_ulogic;
signal d_bus_re, d_bus_re_buf : std_ulogic;
signal i_bus_re, i_bus_re_buf : std_ulogic;
-- pmp faults anyone? --
signal if_pmp_fault : std_ulogic; -- pmp instruction access fault
signal ld_pmp_fault : std_ulogic; -- pmp load access fault
signal st_pmp_fault : std_ulogic; -- pmp store access fault
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (PMP_NUM_REGIONS > pmp_num_regions_critical_c) report "NEORV32 CPU CONFIG WARNING! Number of implemented PMP regions (PMP_NUM_REGIONS = " &
integer'image(PMP_NUM_REGIONS) & ") beyond critical limit (pmp_num_regions_critical_c = " & integer'image(pmp_num_regions_critical_c) &
"). Inserting another register stage (that will increase memory latency by +1 cycle)." severity warning;
-- Data Interface: Access Address ---------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_adr_reg: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
mar <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
if (ctrl_i(ctrl_bus_mo_we_c) = '1') then
mar <= addr_i;
end if;
end if;
end process mem_adr_reg;
-- read-back for exception controller --
mar_o <= mar;
-- alignment check --
misaligned_d_check: process(mar, ctrl_i)
begin
-- check data access --
d_misaligned <= '0'; -- default
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is -- data size
when "00" => -- byte
d_misaligned <= '0';
when "01" => -- half-word
if (mar(0) /= '0') then
d_misaligned <= '1';
end if;
when others => -- word
if (mar(1 downto 0) /= "00") then
d_misaligned <= '1';
end if;
end case;
end process misaligned_d_check;
-- Data Interface: Write Data -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_do_reg: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
mdo <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
if (ctrl_i(ctrl_bus_mo_we_c) = '1') then
mdo <= wdata_i; -- memory data output register (MDO)
end if;
end if;
end process mem_do_reg;
-- byte enable and output data alignment --
byte_enable: process(mar, mdo, ctrl_i)
begin
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is -- data size
when "00" => -- byte
d_bus_wdata(07 downto 00) <= mdo(07 downto 00);
d_bus_wdata(15 downto 08) <= mdo(07 downto 00);
d_bus_wdata(23 downto 16) <= mdo(07 downto 00);
d_bus_wdata(31 downto 24) <= mdo(07 downto 00);
case mar(1 downto 0) is
when "00" => d_bus_ben <= "0001";
when "01" => d_bus_ben <= "0010";
when "10" => d_bus_ben <= "0100";
when others => d_bus_ben <= "1000";
end case;
when "01" => -- half-word
d_bus_wdata(31 downto 16) <= mdo(15 downto 00);
d_bus_wdata(15 downto 00) <= mdo(15 downto 00);
if (mar(1) = '0') then
d_bus_ben <= "0011"; -- low half-word
else
d_bus_ben <= "1100"; -- high half-word
end if;
when others => -- word
d_bus_wdata <= mdo;
d_bus_ben <= "1111"; -- full word
end case;
end process byte_enable;
-- Data Interface: Read Data --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_di_reg: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
mdi <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
if (ctrl_i(ctrl_bus_mi_we_c) = '1') then
mdi <= d_bus_rdata; -- memory data input register (MDI)
end if;
end if;
end process mem_di_reg;
-- input data alignment and sign extension --
read_align: process(mdi, mar, ctrl_i)
variable byte_in_v : std_ulogic_vector(07 downto 0);
variable hword_in_v : std_ulogic_vector(15 downto 0);
begin
-- sub-word input --
case mar(1 downto 0) is
when "00" => byte_in_v := mdi(07 downto 00); hword_in_v := mdi(15 downto 00); -- byte 0 / half-word 0
when "01" => byte_in_v := mdi(15 downto 08); hword_in_v := mdi(15 downto 00); -- byte 1 / half-word 0
when "10" => byte_in_v := mdi(23 downto 16); hword_in_v := mdi(31 downto 16); -- byte 2 / half-word 1
when others => byte_in_v := mdi(31 downto 24); hword_in_v := mdi(31 downto 16); -- byte 3 / half-word 1
end case;
-- actual data size --
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is
when "00" => -- byte
rdata_align(31 downto 08) <= (others => ((not ctrl_i(ctrl_bus_unsigned_c)) and byte_in_v(7))); -- sign extension
rdata_align(07 downto 00) <= byte_in_v;
when "01" => -- half-word
rdata_align(31 downto 16) <= (others => ((not ctrl_i(ctrl_bus_unsigned_c)) and hword_in_v(15))); -- sign extension
rdata_align(15 downto 00) <= hword_in_v; -- high half-word
when others => -- word
rdata_align <= mdi; -- full word
end case;
end process read_align;
-- insert exclusive lock status for SC operations only --
rdata_o <= exclusive_lock_status when (CPU_EXTENSION_RISCV_A = true) and (ctrl_i(ctrl_bus_ch_lock_c) = '1') else rdata_align;
-- Data Access Arbiter --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
data_access_arbiter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
d_arbiter.wr_req <= '0';
d_arbiter.rd_req <= '0';
d_arbiter.err_align <= '0';
d_arbiter.err_bus <= '0';
elsif rising_edge(clk_i) then
-- data access request --
if (d_arbiter.wr_req = '0') and (d_arbiter.rd_req = '0') then -- idle
d_arbiter.wr_req <= ctrl_i(ctrl_bus_wr_c);
d_arbiter.rd_req <= ctrl_i(ctrl_bus_rd_c);
d_arbiter.err_align <= d_misaligned;
d_arbiter.err_bus <= '0';
else -- in progress
d_arbiter.err_align <= (d_arbiter.err_align or d_misaligned) and (not ctrl_i(ctrl_bus_derr_ack_c));
d_arbiter.err_bus <= (d_arbiter.err_bus or d_bus_err_i or (st_pmp_fault and d_arbiter.wr_req) or (ld_pmp_fault and d_arbiter.rd_req)) and
(not ctrl_i(ctrl_bus_derr_ack_c));
if (d_bus_ack_i = '1') or (ctrl_i(ctrl_bus_derr_ack_c) = '1') then -- wait for normal termination / CPU abort
d_arbiter.wr_req <= '0';
d_arbiter.rd_req <= '0';
end if;
end if;
end if;
end process data_access_arbiter;
-- wait for bus transaction to finish --
d_wait_o <= (d_arbiter.wr_req or d_arbiter.rd_req) and (not d_bus_ack_i);
-- output data access error to controller --
ma_load_o <= d_arbiter.rd_req and d_arbiter.err_align;
be_load_o <= d_arbiter.rd_req and d_arbiter.err_bus;
ma_store_o <= d_arbiter.wr_req and d_arbiter.err_align;
be_store_o <= d_arbiter.wr_req and d_arbiter.err_bus;
-- data bus (read/write)--
d_bus_addr_o <= mar;
d_bus_wdata_o <= d_bus_wdata;
d_bus_ben_o <= d_bus_ben;
d_bus_we <= ctrl_i(ctrl_bus_wr_c) and (not d_misaligned) and (not st_pmp_fault); -- no actual write when misaligned or PMP fault
d_bus_re <= ctrl_i(ctrl_bus_rd_c) and (not d_misaligned) and (not ld_pmp_fault); -- no actual read when misaligned or PMP fault
d_bus_we_o <= d_bus_we_buf when (PMP_NUM_REGIONS > pmp_num_regions_critical_c) else d_bus_we;
d_bus_re_o <= d_bus_re_buf when (PMP_NUM_REGIONS > pmp_num_regions_critical_c) else d_bus_re;
d_bus_fence_o <= ctrl_i(ctrl_bus_fence_c);
d_bus_rdata <= d_bus_rdata_i;
-- additional register stage for control signals if using PMP_NUM_REGIONS > pmp_num_regions_critical_c --
pmp_dbus_buffer: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
d_bus_we_buf <= '0';
d_bus_re_buf <= '0';
elsif rising_edge(clk_i) then
d_bus_we_buf <= d_bus_we;
d_bus_re_buf <= d_bus_re;
end if;
end process pmp_dbus_buffer;
-- Reservation Controller (LR/SC [A extension]) -------------------------------------------
-- -------------------------------------------------------------------------------------------
exclusive_access_controller: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
exclusive_lock <= '0';
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_A = true) then
if (ctrl_i(ctrl_trap_c) = '1') or (ctrl_i(ctrl_bus_de_lock_c) = '1') then -- remove lock if entering a trap or executing a non-load-reservate memory access
exclusive_lock <= '0';
elsif (ctrl_i(ctrl_bus_lock_c) = '1') then -- set new lock
exclusive_lock <= '1';
end if;
else
exclusive_lock <= '0';
end if;
end if;
end process exclusive_access_controller;
-- lock status for SC operation --
exclusive_lock_status(data_width_c-1 downto 1) <= (others => '0');
exclusive_lock_status(0) <= not exclusive_lock;
-- output reservation status to control unit (to check if SC should write at all) --
excl_state_o <= exclusive_lock;
-- output to memory system --
i_bus_lock_o <= '0'; -- instruction fetches cannot be locked
d_bus_lock_o <= exclusive_lock;
-- Instruction Fetch Arbiter --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ifetch_arbiter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
i_arbiter.rd_req <= '0';
i_arbiter.err_align <= '0';
i_arbiter.err_bus <= '0';
elsif rising_edge(clk_i) then
-- instruction fetch request --
if (i_arbiter.rd_req = '0') then -- idle
i_arbiter.rd_req <= ctrl_i(ctrl_bus_if_c);
i_arbiter.err_align <= i_misaligned;
i_arbiter.err_bus <= '0';
else -- in progres
i_arbiter.err_align <= (i_arbiter.err_align or i_misaligned) and (not ctrl_i(ctrl_bus_ierr_ack_c));
i_arbiter.err_bus <= (i_arbiter.err_bus or i_bus_err_i or if_pmp_fault) and (not ctrl_i(ctrl_bus_ierr_ack_c));
if (i_bus_ack_i = '1') or (ctrl_i(ctrl_bus_ierr_ack_c) = '1') then -- wait for normal termination / CPU abort
i_arbiter.rd_req <= '0';
end if;
end if;
end if;
end process ifetch_arbiter;
i_arbiter.wr_req <= '0'; -- instruction fetch is read-only
-- wait for bus transaction to finish --
i_wait_o <= i_arbiter.rd_req and (not i_bus_ack_i);
-- output instruction fetch error to controller --
ma_instr_o <= i_arbiter.err_align;
be_instr_o <= i_arbiter.err_bus;
-- instruction bus (read-only) --
i_bus_addr_o <= fetch_pc_i(data_width_c-1 downto 2) & "00"; -- instruction access is always 4-byte aligned (even for compressed instructions)
i_bus_wdata_o <= (others => '0'); -- instruction fetch is read-only
i_bus_ben_o <= (others => '0');
i_bus_we_o <= '0';
i_bus_re <= ctrl_i(ctrl_bus_if_c) and (not i_misaligned) and (not if_pmp_fault); -- no actual read when misaligned or PMP fault
i_bus_re_o <= i_bus_re_buf when (PMP_NUM_REGIONS > pmp_num_regions_critical_c) else i_bus_re;
i_bus_fence_o <= ctrl_i(ctrl_bus_fencei_c);
instr_o <= i_bus_rdata_i;
-- check instruction access address alignment --
i_misaligned <= '0' when (CPU_EXTENSION_RISCV_C = true) else -- no alignment exceptions possible when using C-extension
'1' when (fetch_pc_i(1) = '1') else '0'; -- 32-bit accesses only
-- additional register stage for control signals if using PMP_NUM_REGIONS > pmp_num_regions_critical_c --
pmp_ibus_buffer: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
i_bus_re_buf <= '0';
elsif rising_edge(clk_i) then
i_bus_re_buf <= i_bus_re;
end if;
end process pmp_ibus_buffer;
-- Physical Memory Protection (PMP) -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- compute address masks (ITERATIVE!!!) --
pmp_masks: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
pmp.addr_mask <= (others => (others => def_rst_val_c));
elsif rising_edge(clk_i) then -- address mask computation (not the actual address check!) has a latency of max +32 cycles
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
pmp.addr_mask(r) <= (others => '0');
for i in pmp_g_c to data_width_c-1 loop
pmp.addr_mask(r)(i) <= pmp.addr_mask(r)(i-1) or (not pmp_addr_i(r)(i-1));
end loop; -- i
end loop; -- r
end if;
end process pmp_masks;
-- address access check --
pmp_address_check:
for r in 0 to PMP_NUM_REGIONS-1 generate -- iterate over all regions
pmp.region_i_addr(r) <= fetch_pc_i and pmp.addr_mask(r);
pmp.region_d_addr(r) <= mar and pmp.addr_mask(r);
pmp.region_base(r) <= pmp_addr_i(r)(data_width_c+1 downto 2) and pmp.addr_mask(r);
--
pmp.i_match(r) <= '1' when (pmp.region_i_addr(r)(data_width_c-1 downto pmp_g_c) = pmp.region_base(r)(data_width_c-1 downto pmp_g_c)) else '0';
pmp.d_match(r) <= '1' when (pmp.region_d_addr(r)(data_width_c-1 downto pmp_g_c) = pmp.region_base(r)(data_width_c-1 downto pmp_g_c)) else '0';
end generate; -- r
-- check access type and region's permissions --
pmp_check_permission: process(pmp, pmp_ctrl_i, ctrl_i)
begin
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
if ((ctrl_i(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) = priv_mode_u_c) or (pmp_ctrl_i(r)(pmp_cfg_l_c) = '1')) and -- user privilege level or locked pmp entry -> enforce permissions also for machine mode
(pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) /= pmp_off_mode_c) and -- active entry
(ctrl_i(ctrl_debug_running_c) = '0') then -- disable PMP checks when in debug mode
pmp.if_fault(r) <= pmp.i_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_x_c)); -- fetch access match no execute permission
pmp.ld_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_r_c)); -- load access match no read permission
pmp.st_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_w_c)); -- store access match no write permission
else
pmp.if_fault(r) <= '0';
pmp.ld_fault(r) <= '0';
pmp.st_fault(r) <= '0';
end if;
end loop; -- r
end process pmp_check_permission;
-- final PMP access fault signals --
if_pmp_fault <= or_reduce_f(pmp.if_fault) when (PMP_NUM_REGIONS > 0) else '0';
ld_pmp_fault <= or_reduce_f(pmp.ld_fault) when (PMP_NUM_REGIONS > 0) else '0';
st_pmp_fault <= or_reduce_f(pmp.st_fault) when (PMP_NUM_REGIONS > 0) else '0';
end neorv32_cpu_bus_rtl;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,469 @@
-- #################################################################################################
-- # << NEORV32 - CPU Co-Processor: Bit-Manipulation Co-Processor Unit (RISC-V "B" Extension) >> #
-- # ********************************************************************************************* #
-- # The bit manipulation unit is implemented as co-processor that has a processing latency of 1 #
-- # cycle for logic/arithmetic operations and 3+shamt (=shift amount) cycles for shift(-related) #
-- # operations. Use the FAST_SHIFT_EN option to reduce shift-related instruction's latency to a #
-- # fixed value of 3 cycles latency (using barrel shifters). #
-- # #
-- # Supported sub-extensions (Zb*): #
-- # - Zba: Address generation instructions #
-- # - Zbb: Basic bit-manipulation instructions #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_cpu_cp_bitmanip is
generic (
FAST_SHIFT_EN : boolean -- use barrel shifter for shift operations
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
start_i : in std_ulogic; -- trigger operation
-- data input --
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
shamt_i : in std_ulogic_vector(index_size_f(data_width_c)-1 downto 0); -- shift amount
-- result and status --
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operation result
valid_o : out std_ulogic -- data output valid
);
end neorv32_cpu_cp_bitmanip;
architecture neorv32_cpu_cp_bitmanip_rtl of neorv32_cpu_cp_bitmanip is
-- Sub-extension configuration --
constant zbb_en_c : boolean := true;
constant zba_en_c : boolean := true;
-- --------------------------- --
-- commands: Zbb - logic with negate --
constant op_andn_c : natural := 0;
constant op_orn_c : natural := 1;
constant op_xnor_c : natural := 2;
-- commands: Zbb - count leading/trailing zero bits --
constant op_clz_c : natural := 3;
constant op_ctz_c : natural := 4;
-- commands: Zbb - count population --
constant op_cpop_c : natural := 5;
-- commands: Zbb - integer minimum/maximum --
constant op_max_c : natural := 6; -- signed/unsigned
constant op_min_c : natural := 7; -- signed/unsigned
-- commands: Zbb - sign- and zero-extension --
constant op_sextb_c : natural := 8;
constant op_sexth_c : natural := 9;
constant op_zexth_c : natural := 10;
-- commands: Zbb - bitwise rotation --
constant op_rol_c : natural := 11;
constant op_ror_c : natural := 12; -- rori
-- commands: Zbb - or-combine --
constant op_orcb_c : natural := 13;
-- commands: Zbb - byte-reverse --
constant op_rev8_c : natural := 14;
-- commands: Zba - shifted add --
constant op_sh1add_c : natural := 15;
constant op_sh2add_c : natural := 16;
constant op_sh3add_c : natural := 17;
--
constant op_width_c : natural := 18;
-- controller --
type ctrl_state_t is (S_IDLE, S_START_SHIFT, S_BUSY_SHIFT);
signal ctrl_state : ctrl_state_t;
signal cmd, cmd_buf : std_ulogic_vector(op_width_c-1 downto 0);
signal valid : std_ulogic;
-- operand buffers --
signal rs1_reg : std_ulogic_vector(data_width_c-1 downto 0);
signal rs2_reg : std_ulogic_vector(data_width_c-1 downto 0);
signal sha_reg : std_ulogic_vector(index_size_f(data_width_c)-1 downto 0);
signal less_ff : std_ulogic;
-- serial shifter --
type shifter_t is record
start : std_ulogic;
run : std_ulogic;
bcnt : std_ulogic_vector(index_size_f(data_width_c) downto 0); -- bit counter
cnt : std_ulogic_vector(index_size_f(data_width_c) downto 0); -- iteration counter
cnt_max : std_ulogic_vector(index_size_f(data_width_c) downto 0);
sreg : std_ulogic_vector(data_width_c-1 downto 0);
end record;
signal shifter : shifter_t;
-- barrel shifter --
type bs_level_t is array (index_size_f(data_width_c) downto 0) of std_ulogic_vector(data_width_c-1 downto 0);
signal bs_level : bs_level_t;
-- operation results --
type res_t is array (0 to op_width_c-1) of std_ulogic_vector(data_width_c-1 downto 0);
signal res_int, res_out : res_t;
-- shifted-add unit --
signal adder_core : std_ulogic_vector(data_width_c-1 downto 0);
begin
-- Sub-Extension Configuration ------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report
"Implementing bit-manipulation (B) sub-extensions: " &
cond_sel_string_f(zbb_en_c, "Zbb", "") &
cond_sel_string_f(zba_en_c, "Zba", "") &
""
severity note;
-- Instruction Decoding (One-Hot) ---------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- a minimal decoding logic is used here -> just to distinguish between B.Zbb instructions
-- a more specific decoding and instruction check is done by the CPU control unit
-- Zbb - Basic bit-manipulation instructions --
cmd(op_andn_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "10") and (ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) = "11") else '0';
cmd(op_orn_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "10") and (ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) = "10") else '0';
cmd(op_xnor_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "10") and (ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) = "00") else '0';
--
cmd(op_max_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "00") and (ctrl_i(ctrl_ir_funct12_5_c) = '1') and (ctrl_i(ctrl_ir_funct3_1_c) = '1') else '0';
cmd(op_min_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "00") and (ctrl_i(ctrl_ir_funct12_5_c) = '1') and (ctrl_i(ctrl_ir_funct3_1_c) = '0') else '0';
cmd(op_zexth_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "00") and (ctrl_i(ctrl_ir_funct12_5_c) = '0') else '0';
--
cmd(op_orcb_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "01") and (ctrl_i(ctrl_ir_funct12_7_c) = '1') else '0';
--
cmd(op_clz_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "000") else '0';
cmd(op_ctz_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "001") else '0';
cmd(op_cpop_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "010") else '0';
cmd(op_sextb_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "100") else '0';
cmd(op_sexth_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c) = '0') and (ctrl_i(ctrl_ir_funct12_2_c downto ctrl_ir_funct12_0_c) = "101") else '0';
cmd(op_rol_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c) = "001") and (ctrl_i(ctrl_ir_opcode7_5_c) = '1') else '0';
cmd(op_ror_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c) = "101") else '0';
cmd(op_rev8_c) <= '1' when (zbb_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "11") and (ctrl_i(ctrl_ir_funct12_7_c) = '1') else '0';
-- Zba - Address generation instructions --
cmd(op_sh1add_c) <= '1' when (zba_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "01") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_1_c) = "01") else '0';
cmd(op_sh2add_c) <= '1' when (zba_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "01") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_1_c) = "10") else '0';
cmd(op_sh3add_c) <= '1' when (zba_en_c = true) and (ctrl_i(ctrl_ir_funct12_10_c downto ctrl_ir_funct12_9_c) = "01") and (ctrl_i(ctrl_ir_funct12_7_c) = '0') and (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_1_c) = "11") else '0';
-- Co-Processor Controller ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
coprocessor_ctrl: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
ctrl_state <= S_IDLE;
cmd_buf <= (others => def_rst_val_c);
rs1_reg <= (others => def_rst_val_c);
rs2_reg <= (others => def_rst_val_c);
sha_reg <= (others => def_rst_val_c);
less_ff <= def_rst_val_c;
shifter.start <= '0';
valid <= '0';
elsif rising_edge(clk_i) then
-- defaults --
shifter.start <= '0';
valid <= '0';
-- fsm --
case ctrl_state is
when S_IDLE => -- wait for operation trigger
-- ------------------------------------------------------------
if (start_i = '1') then
less_ff <= cmp_i(cmp_less_c);
cmd_buf <= cmd;
rs1_reg <= rs1_i;
rs2_reg <= rs2_i;
sha_reg <= shamt_i;
if ((cmd(op_clz_c) or cmd(op_ctz_c) or cmd(op_cpop_c) or cmd(op_ror_c) or cmd(op_rol_c)) = '1') then -- multi-cycle shift operation
if (FAST_SHIFT_EN = false) then -- default: iterative computation
shifter.start <= '1';
ctrl_state <= S_START_SHIFT;
else -- full-parallel computation
ctrl_state <= S_BUSY_SHIFT;
end if;
else
valid <= '1';
ctrl_state <= S_IDLE;
end if;
end if;
when S_START_SHIFT => -- one cycle delay to start shift operation
-- ------------------------------------------------------------
ctrl_state <= S_BUSY_SHIFT;
when S_BUSY_SHIFT => -- wait for multi-cycle shift operation to finish
-- ------------------------------------------------------------
if (shifter.run = '0') then
valid <= '1';
ctrl_state <= S_IDLE;
end if;
when others => -- undefined
-- ------------------------------------------------------------
ctrl_state <= S_IDLE;
end case;
end if;
end process coprocessor_ctrl;
-- Shifter Function Core (iterative: small but slow) --------------------------------------
-- -------------------------------------------------------------------------------------------
serial_shifter:
if (FAST_SHIFT_EN = false) generate
shifter_unit: process(rstn_i, clk_i)
variable new_bit_v : std_ulogic;
begin
if (rstn_i = '0') then
shifter.cnt <= (others => def_rst_val_c);
shifter.sreg <= (others => def_rst_val_c);
shifter.cnt_max <= (others => def_rst_val_c);
shifter.bcnt <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
if (shifter.start = '1') then -- trigger new shift
shifter.cnt <= (others => '0');
-- shift operand --
if (cmd_buf(op_clz_c) = '1') or (cmd_buf(op_rol_c) = '1') then -- count LEADING zeros / rotate LEFT
shifter.sreg <= bit_rev_f(rs1_reg); -- reverse - we can only do right shifts here
else -- ctz, cpop, ror
shifter.sreg <= rs1_reg;
end if;
-- max shift amount --
if (cmd_buf(op_cpop_c) = '1') then -- population count
shifter.cnt_max <= (others => '0');
shifter.cnt_max(shifter.cnt_max'left) <= '1';
else
shifter.cnt_max <= '0' & sha_reg;
end if;
shifter.bcnt <= (others => '0');
elsif (shifter.run = '1') then -- right shifts only
new_bit_v := ((cmd_buf(op_ror_c) or cmd_buf(op_rol_c)) and shifter.sreg(0)) or (cmd_buf(op_clz_c) or cmd_buf(op_ctz_c));
shifter.sreg <= new_bit_v & shifter.sreg(shifter.sreg'left downto 1); -- ro[r/l]/lsr(for counting)
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) + 1); -- iteration counter
if (shifter.sreg(0) = '1') then
shifter.bcnt <= std_ulogic_vector(unsigned(shifter.bcnt) + 1); -- bit counter
end if;
end if;
end if;
end process shifter_unit;
end generate;
-- run control --
serial_shifter_ctrl:
if (FAST_SHIFT_EN = false) generate
shifter_unit_ctrl: process(cmd_buf, shifter)
begin
-- keep shifting until ... --
if (cmd_buf(op_clz_c) = '1') or (cmd_buf(op_ctz_c) = '1') then -- count leading/trailing zeros
shifter.run <= not shifter.sreg(0);
else -- population count / rotate
if (shifter.cnt = shifter.cnt_max) then
shifter.run <= '0';
else
shifter.run <= '1';
end if;
end if;
end process shifter_unit_ctrl;
end generate;
-- Shifter Function Core (parallel: fast but large) ---------------------------------------
-- -------------------------------------------------------------------------------------------
barrel_shifter_async_sync:
if (FAST_SHIFT_EN = true) generate
shifter_unit_fast: process(rstn_i, clk_i)
variable new_bit_v : std_ulogic;
begin
if (rstn_i = '0') then
shifter.cnt <= (others => def_rst_val_c);
shifter.sreg <= (others => def_rst_val_c);
shifter.bcnt <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
-- population count --
shifter.bcnt <= std_ulogic_vector(to_unsigned(popcount_f(rs1_reg), shifter.bcnt'length));
-- count leading/trailing zeros --
if cmd_buf(op_clz_c) = '1' then -- leading
shifter.cnt <= std_ulogic_vector(to_unsigned(leading_zeros_f(rs1_reg), shifter.cnt'length));
else -- trailing
shifter.cnt <= std_ulogic_vector(to_unsigned(leading_zeros_f(bit_rev_f(rs1_reg)), shifter.cnt'length));
end if;
-- barrel shifter --
shifter.sreg <= bs_level(0); -- rol/ror[i]
end if;
end process shifter_unit_fast;
shifter.run <= '0'; -- we are done already!
end generate;
-- barrel shifter array --
barrel_shifter_async:
if (FAST_SHIFT_EN = true) generate
shifter_unit_async: process(rs1_reg, sha_reg, cmd_buf, bs_level)
begin
-- input level: convert left shifts to right shifts --
if (cmd_buf(op_rol_c) = '1') then -- is left shift?
bs_level(index_size_f(data_width_c)) <= bit_rev_f(rs1_reg); -- reverse bit order of input operand
else
bs_level(index_size_f(data_width_c)) <= rs1_reg;
end if;
-- shifter array --
for i in index_size_f(data_width_c)-1 downto 0 loop
if (sha_reg(i) = '1') then
bs_level(i)(data_width_c-1 downto data_width_c-(2**i)) <= bs_level(i+1)((2**i)-1 downto 0);
bs_level(i)((data_width_c-(2**i))-1 downto 0) <= bs_level(i+1)(data_width_c-1 downto 2**i);
else
bs_level(i) <= bs_level(i+1);
end if;
end loop;
end process shifter_unit_async;
end generate;
-- Shifted-Add Core -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
shift_adder: process(rs1_reg, rs2_reg, ctrl_i)
variable opb_v : std_ulogic_vector(data_width_c-1 downto 0);
begin
case ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_1_c) is
when "01" => opb_v := rs1_reg(rs1_reg'left-1 downto 0) & '0'; -- << 1
when "10" => opb_v := rs1_reg(rs1_reg'left-2 downto 0) & "00"; -- << 2
when "11" => opb_v := rs1_reg(rs1_reg'left-3 downto 0) & "000"; -- << 3
when others => opb_v := rs1_reg(rs1_reg'left-1 downto 0) & '0'; -- undefined
end case;
adder_core <= std_ulogic_vector(unsigned(rs2_reg) + unsigned(opb_v));
end process shift_adder;
-- Operation Results ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- logic with negate --
res_int(op_andn_c) <= rs1_reg and (not rs2_reg); -- logical and-not
res_int(op_orn_c) <= rs1_reg or (not rs2_reg); -- logical or-not
res_int(op_xnor_c) <= rs1_reg xor (not rs2_reg); -- logical xor-not
-- count leading/trailing zeros --
res_int(op_clz_c)(data_width_c-1 downto shifter.cnt'left+1) <= (others => '0');
res_int(op_clz_c)(shifter.cnt'left downto 0) <= shifter.cnt;
res_int(op_ctz_c) <= (others => '0'); -- unused/redundant
-- count set bits --
res_int(op_cpop_c)(data_width_c-1 downto shifter.bcnt'left+1) <= (others => '0');
res_int(op_cpop_c)(shifter.bcnt'left downto 0) <= shifter.bcnt;
-- min/max select --
res_int(op_min_c) <= rs1_reg when ((less_ff xor cmd_buf(op_max_c)) = '1') else rs2_reg;
res_int(op_max_c) <= (others => '0'); -- unused/redundant
-- sign-extension --
res_int(op_sextb_c)(data_width_c-1 downto 8) <= (others => rs1_reg(7));
res_int(op_sextb_c)(7 downto 0) <= rs1_reg(7 downto 0); -- sign-extend byte
res_int(op_sexth_c)(data_width_c-1 downto 16) <= (others => rs1_reg(15));
res_int(op_sexth_c)(15 downto 0) <= rs1_reg(15 downto 0); -- sign-extend half-word
res_int(op_zexth_c)(data_width_c-1 downto 16) <= (others => '0');
res_int(op_zexth_c)(15 downto 0) <= rs1_reg(15 downto 0); -- zero-extend half-word
-- rotate right/left --
res_int(op_ror_c) <= shifter.sreg;
res_int(op_rol_c) <= bit_rev_f(shifter.sreg); -- reverse to compensate internal right-only shifts
-- or-combine.byte --
or_combine_gen:
for i in 0 to (data_width_c/8)-1 generate -- sub-byte loop
res_int(op_orcb_c)(i*8+7 downto i*8) <= (others => or_reduce_f(rs1_reg(i*8+7 downto i*8)));
end generate; -- i
-- reversal.8 (byte swap) --
res_int(op_rev8_c) <= bswap32_f(rs1_reg);
-- address generation instructions --
res_int(op_sh1add_c) <= adder_core;
res_int(op_sh2add_c) <= (others => '0'); -- unused/redundant
res_int(op_sh3add_c) <= (others => '0'); -- unused/redundant
-- Output Selector ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
res_out(op_andn_c) <= res_int(op_andn_c) when (cmd_buf(op_andn_c) = '1') else (others => '0');
res_out(op_orn_c) <= res_int(op_orn_c) when (cmd_buf(op_orn_c) = '1') else (others => '0');
res_out(op_xnor_c) <= res_int(op_xnor_c) when (cmd_buf(op_xnor_c) = '1') else (others => '0');
res_out(op_clz_c) <= res_int(op_clz_c) when ((cmd_buf(op_clz_c) or cmd_buf(op_ctz_c)) = '1') else (others => '0');
res_out(op_ctz_c) <= (others => '0'); -- unused/redundant
res_out(op_cpop_c) <= res_int(op_cpop_c) when (cmd_buf(op_cpop_c) = '1') else (others => '0');
res_out(op_min_c) <= res_int(op_min_c) when ((cmd_buf(op_min_c) or cmd_buf(op_max_c)) = '1') else (others => '0');
res_out(op_max_c) <= (others => '0'); -- unused/redundant
res_out(op_sextb_c) <= res_int(op_sextb_c) when (cmd_buf(op_sextb_c) = '1') else (others => '0');
res_out(op_sexth_c) <= res_int(op_sexth_c) when (cmd_buf(op_sexth_c) = '1') else (others => '0');
res_out(op_zexth_c) <= res_int(op_zexth_c) when (cmd_buf(op_zexth_c) = '1') else (others => '0');
res_out(op_ror_c) <= res_int(op_ror_c) when (cmd_buf(op_ror_c) = '1') else (others => '0');
res_out(op_rol_c) <= res_int(op_rol_c) when (cmd_buf(op_rol_c) = '1') else (others => '0');
res_out(op_orcb_c) <= res_int(op_orcb_c) when (cmd_buf(op_orcb_c) = '1') else (others => '0');
res_out(op_rev8_c) <= res_int(op_rev8_c) when (cmd_buf(op_rev8_c) = '1') else (others => '0');
--
res_out(op_sh1add_c) <= res_int(op_sh1add_c) when ((cmd_buf(op_sh1add_c) or cmd_buf(op_sh2add_c) or cmd_buf(op_sh3add_c)) = '1') else (others => '0');
res_out(op_sh2add_c) <= (others => '0'); -- unused/redundant
res_out(op_sh3add_c) <= (others => '0'); -- unused/redundant
-- Output Gate ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
output_gate: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
res_o <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
res_o <= (others => '0');
if (valid = '1') then
res_o <= res_out(op_andn_c) or res_out(op_orn_c) or res_out(op_xnor_c) or
res_out(op_clz_c) or res_out(op_cpop_c) or -- res_out(op_ctz_c) is unused here
res_out(op_min_c) or -- res_out(op_max_c) is unused here
res_out(op_sextb_c) or res_out(op_sexth_c) or res_out(op_zexth_c) or
res_out(op_ror_c) or res_out(op_rol_c) or
res_out(op_orcb_c) or res_out(op_rev8_c) or
res_out(op_sh1add_c); -- res_out(op_sh2add_c) and res_out(op_sh3add_c) are unused here
end if;
end if;
end process output_gate;
-- valid output --
valid_o <= valid;
end neorv32_cpu_cp_bitmanip_rtl;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,343 @@
-- #################################################################################################
-- # << NEORV32 - CPU Co-Processor: Integer Multiplier/Divider Unit (RISC-V "M" Extension) >> #
-- # ********************************************************************************************* #
-- # Multiplier and Divider unit. Implements the RISC-V M CPU extension. #
-- # #
-- # Multiplier core (signed/unsigned) uses classical serial algorithm. Unit latency: 31+3 cycles #
-- # Divider core (unsigned) uses classical serial algorithm. Unit latency: 32+4 cycles #
-- # #
-- # Multiplications can be mapped to DSP blocks (faster!) when FAST_MUL_EN = true. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_cpu_cp_muldiv is
generic (
FAST_MUL_EN : boolean; -- use DSPs for faster multiplication
DIVISION_EN : boolean -- implement divider hardware
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
start_i : in std_ulogic; -- trigger operation
-- data input --
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
-- result and status --
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operation result
valid_o : out std_ulogic -- data output valid
);
end neorv32_cpu_cp_muldiv;
architecture neorv32_cpu_cp_muldiv_rtl of neorv32_cpu_cp_muldiv is
-- operations --
constant cp_op_mul_c : std_ulogic_vector(2 downto 0) := "000"; -- mul
constant cp_op_mulh_c : std_ulogic_vector(2 downto 0) := "001"; -- mulh
constant cp_op_mulhsu_c : std_ulogic_vector(2 downto 0) := "010"; -- mulhsu
constant cp_op_mulhu_c : std_ulogic_vector(2 downto 0) := "011"; -- mulhu
constant cp_op_div_c : std_ulogic_vector(2 downto 0) := "100"; -- div
constant cp_op_divu_c : std_ulogic_vector(2 downto 0) := "101"; -- divu
constant cp_op_rem_c : std_ulogic_vector(2 downto 0) := "110"; -- rem
constant cp_op_remu_c : std_ulogic_vector(2 downto 0) := "111"; -- remu
-- controller --
type state_t is (IDLE, DIV_PREPROCESS, PROCESSING, FINALIZE);
signal state : state_t;
signal cnt : std_ulogic_vector(4 downto 0);
signal cp_op : std_ulogic_vector(2 downto 0); -- operation to execute
signal cp_op_ff : std_ulogic_vector(2 downto 0); -- operation that was executed
signal start_div : std_ulogic;
signal start_mul : std_ulogic;
signal operation : std_ulogic;
signal div_opy : std_ulogic_vector(data_width_c-1 downto 0);
signal rs1_is_signed : std_ulogic;
signal rs2_is_signed : std_ulogic;
signal opy_is_zero : std_ulogic;
signal div_res_corr : std_ulogic;
signal out_en : std_ulogic;
-- divider core --
signal remainder : std_ulogic_vector(data_width_c-1 downto 0);
signal quotient : std_ulogic_vector(data_width_c-1 downto 0);
signal div_sub : std_ulogic_vector(data_width_c downto 0);
signal div_sign_comp_in : std_ulogic_vector(data_width_c-1 downto 0);
signal div_sign_comp : std_ulogic_vector(data_width_c-1 downto 0);
signal div_res : std_ulogic_vector(data_width_c-1 downto 0);
-- multiplier core --
signal mul_product : std_ulogic_vector(63 downto 0);
signal mul_do_add : std_ulogic_vector(data_width_c downto 0);
signal mul_sign_cycle : std_ulogic;
signal mul_p_sext : std_ulogic;
signal mul_op_x : signed(32 downto 0); -- for using DSPs
signal mul_op_y : signed(32 downto 0); -- for using DSPs
begin
-- Co-Processor Controller ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
coprocessor_ctrl: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
state <= IDLE;
div_opy <= (others => def_rst_val_c);
cnt <= (others => def_rst_val_c);
cp_op_ff <= (others => def_rst_val_c);
start_div <= '0';
out_en <= '0';
valid_o <= '0';
div_res_corr <= def_rst_val_c;
opy_is_zero <= def_rst_val_c;
elsif rising_edge(clk_i) then
-- defaults --
start_div <= '0';
out_en <= '0';
valid_o <= '0';
-- FSM --
case state is
when IDLE =>
cp_op_ff <= cp_op;
cnt <= "11110";
if (start_i = '1') then
if (operation = '1') and (DIVISION_EN = true) then -- division
start_div <= '1';
state <= DIV_PREPROCESS;
else -- multiplication
if (FAST_MUL_EN = true) then
valid_o <= '1';
state <= FINALIZE;
else
state <= PROCESSING;
end if;
end if;
end if;
when DIV_PREPROCESS =>
-- check relevant input signs --
if (cp_op = cp_op_div_c) then -- result sign compensation for div?
div_res_corr <= rs1_i(rs1_i'left) xor rs2_i(rs2_i'left);
elsif (cp_op = cp_op_rem_c) then -- result sign compensation for rem?
div_res_corr <= rs1_i(rs1_i'left);
else
div_res_corr <= '0';
end if;
-- divide by zero? --
opy_is_zero <= not or_reduce_f(rs2_i); -- set if rs2 = 0
-- abs(rs2) --
if ((rs2_i(rs2_i'left) and rs2_is_signed) = '1') then -- signed division?
div_opy <= std_ulogic_vector(0 - unsigned(rs2_i)); -- make positive
else
div_opy <= rs2_i;
end if;
--
state <= PROCESSING;
when PROCESSING =>
cnt <= std_ulogic_vector(unsigned(cnt) - 1);
if (cnt = "00000") then
valid_o <= '1';
state <= FINALIZE;
end if;
when FINALIZE =>
out_en <= '1';
state <= IDLE;
when others =>
state <= IDLE;
end case;
end if;
end process coprocessor_ctrl;
-- co-processor command --
cp_op <= ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c);
-- operation: 0=mul, 1=div --
operation <= '1' when (cp_op(2) = '1') else '0';
-- opx (rs1) signed? --
rs1_is_signed <= '1' when (cp_op = cp_op_mulh_c) or (cp_op = cp_op_mulhsu_c) or (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) else '0';
-- opy (rs2) signed? --
rs2_is_signed <= '1' when (cp_op = cp_op_mulh_c) or (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) else '0';
-- start MUL operation (do it fast!) --
start_mul <= '1' when (state = IDLE) and (start_i = '1') and (operation = '0') else '0';
-- Multiplier Core (signed/unsigned) ------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- iterative multiplication (bit-serial) --
multiplier_core_serial:
if (FAST_MUL_EN = false) generate
multiplier_core: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
mul_product <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
if (start_mul = '1') then -- start new multiplication
mul_product(63 downto 32) <= (others => '0');
mul_product(31 downto 00) <= rs2_i;
elsif (state = PROCESSING) or (state = FINALIZE) then -- processing step or sign-finalization step
mul_product(63 downto 31) <= mul_do_add(32 downto 0);
mul_product(30 downto 00) <= mul_product(31 downto 1);
end if;
end if;
end process multiplier_core;
end generate;
-- parallel multiplication (using DSP blocks) --
multiplier_core_dsp:
if (FAST_MUL_EN = true) generate
multiplier_core: process(clk_i)
variable tmp_v : signed(65 downto 0);
begin
if rising_edge(clk_i) then
if (start_mul = '1') then
mul_op_x <= signed((rs1_i(rs1_i'left) and rs1_is_signed) & rs1_i);
mul_op_y <= signed((rs2_i(rs2_i'left) and rs2_is_signed) & rs2_i);
end if;
tmp_v := mul_op_x * mul_op_y;
mul_product <= std_ulogic_vector(tmp_v(63 downto 0));
--mul_buf_ff <= mul_op_x * mul_op_y;
--mul_product <= std_ulogic_vector(mul_buf_ff(63 downto 0)); -- let the register balancing do the magic here
end if;
end process multiplier_core;
end generate;
-- do another addition (bit-serial) --
mul_update: process(mul_product, mul_sign_cycle, mul_p_sext, rs1_is_signed, rs1_i)
begin
-- current bit of rs2_i to take care of --
if (mul_product(0) = '1') then -- multiply with 1
if (mul_sign_cycle = '1') then -- for signed operations only: take care of negative weighted MSB -> multiply with -1
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((rs1_i(rs1_i'left) and rs1_is_signed) & rs1_i));
else -- multiply with +1
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((rs1_i(rs1_i'left) and rs1_is_signed) & rs1_i));
end if;
else -- multiply with 0
mul_do_add <= mul_p_sext & mul_product(63 downto 32);
end if;
end process mul_update;
-- sign control --
mul_sign_cycle <= rs2_is_signed when (state = FINALIZE) else '0';
mul_p_sext <= mul_product(mul_product'left) and rs1_is_signed;
-- Divider Core (unsigned) ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
divider_core_serial:
if (DIVISION_EN = true) generate
divider_core: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
quotient <= (others => def_rst_val_c);
remainder <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
if (start_div = '1') then -- start new division
if ((rs1_i(rs1_i'left) and rs1_is_signed) = '1') then -- signed division?
quotient <= std_ulogic_vector(0 - unsigned(rs1_i)); -- make positive
else
quotient <= rs1_i;
end if;
remainder <= (others => '0');
elsif (state = PROCESSING) or (state = FINALIZE) then -- running?
quotient <= quotient(30 downto 0) & (not div_sub(32));
if (div_sub(32) = '0') then -- still overflowing
remainder <= div_sub(31 downto 0);
else -- underflow
remainder <= remainder(30 downto 0) & quotient(31);
end if;
end if;
end if;
end process divider_core;
-- try another subtraction --
div_sub <= std_ulogic_vector(unsigned('0' & remainder(30 downto 0) & quotient(31)) - unsigned('0' & div_opy));
-- result sign compensation --
div_sign_comp_in <= quotient when (cp_op = cp_op_div_c) else remainder;
div_sign_comp <= std_ulogic_vector(0 - unsigned(div_sign_comp_in));
div_res <= div_sign_comp when (div_res_corr = '1') and (opy_is_zero = '0') else div_sign_comp_in;
end generate;
-- no divider --
divider_core_serial_none:
if (DIVISION_EN = false) generate
remainder <= (others => '0');
quotient <= (others => '0');
div_res <= (others => '0');
end generate;
-- Data Output ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
operation_result: process(out_en, cp_op_ff, mul_product, div_res, quotient, opy_is_zero, rs1_i, remainder)
begin
if (out_en = '1') then
case cp_op_ff is
when cp_op_mul_c =>
res_o <= mul_product(31 downto 00);
when cp_op_mulh_c | cp_op_mulhsu_c | cp_op_mulhu_c =>
res_o <= mul_product(63 downto 32);
when cp_op_div_c =>
res_o <= div_res;
when cp_op_divu_c =>
res_o <= quotient;
when cp_op_rem_c =>
if (opy_is_zero = '0') then
res_o <= div_res;
else
res_o <= rs1_i;
end if;
when others => -- cp_op_remu_c
res_o <= remainder;
end case;
else
res_o <= (others => '0');
end if;
end process operation_result;
end neorv32_cpu_cp_muldiv_rtl;

View File

@ -0,0 +1,181 @@
-- #################################################################################################
-- # << NEORV32 - CPU Co-Processor: Shifter (CPU Core ISA) >> #
-- # ********************************************************************************************* #
-- # Bit-shift unit for base ISA. #
-- # FAST_SHIFT_EN = false (default): Use bit-serial shifter architecture (small but slow) #
-- # FAST_SHIFT_EN = true: Use barrel shifter architecture (large but fast) #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_cpu_cp_shifter is
generic (
FAST_SHIFT_EN : boolean -- use barrel shifter for shift operations
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
start_i : in std_ulogic; -- trigger operation
-- data input --
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
shamt_i : in std_ulogic_vector(index_size_f(data_width_c)-1 downto 0); -- shift amount
-- result and status --
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operation result
valid_o : out std_ulogic -- data output valid
);
end neorv32_cpu_cp_shifter;
architecture neorv32_cpu_cp_shifter_rtl of neorv32_cpu_cp_shifter is
-- serial shifter --
type shifter_t is record
busy : std_ulogic;
busy_ff : std_ulogic;
done : std_ulogic;
cnt : std_ulogic_vector(index_size_f(data_width_c)-1 downto 0);
sreg : std_ulogic_vector(data_width_c-1 downto 0);
res : std_ulogic_vector(data_width_c-1 downto 0);
end record;
signal shifter : shifter_t;
-- barrel shifter --
type bs_level_t is array (index_size_f(data_width_c) downto 0) of std_ulogic_vector(data_width_c-1 downto 0);
signal bs_level : bs_level_t;
signal bs_result : std_ulogic_vector(data_width_c-1 downto 0);
begin
-- Iterative Shifter Core (small but slow) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
serial_shifter_sync:
if (FAST_SHIFT_EN = false) generate
shifter_unit_sync: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
shifter.busy <= '0';
shifter.busy_ff <= def_rst_val_c;
shifter.sreg <= (others => def_rst_val_c);
shifter.cnt <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
shifter.busy_ff <= shifter.busy;
if (start_i = '1') then
shifter.busy <= '1';
elsif (shifter.done = '1') then
shifter.busy <= '0';
end if;
--
if (start_i = '1') then -- trigger new shift
shifter.sreg <= rs1_i; -- shift operand
shifter.cnt <= shamt_i; -- shift amount
elsif (or_reduce_f(shifter.cnt) = '1') then -- running shift (cnt != 0)
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 1);
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
shifter.sreg <= shifter.sreg(shifter.sreg'left-1 downto 0) & '0';
else -- SRL: shift right logical / SRA: shift right arithmetical
shifter.sreg <= (shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 1);
end if;
end if;
end if;
end process shifter_unit_sync;
end generate;
-- shift control/output --
serial_shifter_ctrl:
if (FAST_SHIFT_EN = false) generate
shifter.done <= not or_reduce_f(shifter.cnt(shifter.cnt'left downto 1));
valid_o <= shifter.busy and shifter.done;
res_o <= shifter.sreg when (shifter.busy = '0') and (shifter.busy_ff = '1') else (others => '0');
end generate;
-- Barrel Shifter Core (fast but large) ---------------------------------------------------
-- -------------------------------------------------------------------------------------------
barrel_shifter_async:
if (FAST_SHIFT_EN = true) generate
shifter_unit_async: process(rs1_i, shamt_i, ctrl_i, bs_level)
begin
-- input level: convert left shifts to right shifts --
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- is left shift?
bs_level(index_size_f(data_width_c)) <= bit_rev_f(rs1_i); -- reverse bit order of input operand
else
bs_level(index_size_f(data_width_c)) <= rs1_i;
end if;
-- shifter array --
for i in index_size_f(data_width_c)-1 downto 0 loop
if (shamt_i(i) = '1') then
bs_level(i)(data_width_c-1 downto data_width_c-(2**i)) <= (others => (bs_level(i+1)(data_width_c-1) and ctrl_i(ctrl_alu_shift_ar_c)));
bs_level(i)((data_width_c-(2**i))-1 downto 0) <= bs_level(i+1)(data_width_c-1 downto 2**i);
else
bs_level(i) <= bs_level(i+1);
end if;
end loop;
-- re-convert original left shifts --
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then
bs_result <= bit_rev_f(bs_level(0));
else
bs_result <= bs_level(0);
end if;
end process shifter_unit_async;
end generate;
-- output register --
barrel_shifter_sync:
if (FAST_SHIFT_EN = true) generate
shifter_unit_sync: process(clk_i)
begin
if rising_edge(clk_i) then
res_o <= (others => '0');
if (start_i = '1') then
res_o <= bs_result;
end if;
end if;
end process shifter_unit_sync;
end generate;
-- shift control/output --
barrel_shifter_ctrl:
if (FAST_SHIFT_EN = true) generate
valid_o <= start_i;
end generate;
end neorv32_cpu_cp_shifter_rtl;

View File

@ -0,0 +1,453 @@
-- #################################################################################################
-- # << NEORV32 - CPU: Compressed Instructions Decoder (RISC-V "C" Extension) >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_cpu_decompressor is
port (
-- instruction input --
ci_instr16_i : in std_ulogic_vector(15 downto 0); -- compressed instruction input
-- instruction output --
ci_illegal_o : out std_ulogic; -- is an illegal compressed instruction
ci_instr32_o : out std_ulogic_vector(31 downto 0) -- 32-bit decompressed instruction
);
end neorv32_cpu_decompressor;
architecture neorv32_cpu_decompressor_rtl of neorv32_cpu_decompressor is
-- compressed instruction layout --
constant ci_opcode_lsb_c : natural := 0;
constant ci_opcode_msb_c : natural := 1;
constant ci_rd_3_lsb_c : natural := 2;
constant ci_rd_3_msb_c : natural := 4;
constant ci_rd_5_lsb_c : natural := 7;
constant ci_rd_5_msb_c : natural := 11;
constant ci_rs1_3_lsb_c : natural := 7;
constant ci_rs1_3_msb_c : natural := 9;
constant ci_rs1_5_lsb_c : natural := 7;
constant ci_rs1_5_msb_c : natural := 11;
constant ci_rs2_3_lsb_c : natural := 2;
constant ci_rs2_3_msb_c : natural := 4;
constant ci_rs2_5_lsb_c : natural := 2;
constant ci_rs2_5_msb_c : natural := 6;
constant ci_funct3_lsb_c : natural := 13;
constant ci_funct3_msb_c : natural := 15;
begin
-- Compressed Instruction Decoder ---------------------------------------------------------
-- -------------------------------------------------------------------------------------------
decompressor: process(ci_instr16_i)
variable imm20_v : std_ulogic_vector(20 downto 0);
variable imm12_v : std_ulogic_vector(12 downto 0);
begin
-- defaults --
ci_illegal_o <= '0';
ci_instr32_o <= (others => '0');
-- helper: 22-bit sign-extended immediate for J/JAL --
imm20_v := (others => ci_instr16_i(12)); -- sign extension
imm20_v(00):= '0';
imm20_v(01):= ci_instr16_i(3);
imm20_v(02):= ci_instr16_i(4);
imm20_v(03):= ci_instr16_i(5);
imm20_v(04):= ci_instr16_i(11);
imm20_v(05):= ci_instr16_i(2);
imm20_v(06):= ci_instr16_i(7);
imm20_v(07):= ci_instr16_i(6);
imm20_v(08):= ci_instr16_i(9);
imm20_v(09):= ci_instr16_i(10);
imm20_v(10):= ci_instr16_i(8);
imm20_v(11):= ci_instr16_i(12);
-- helper: 12-bit sign-extended immediate for branches --
imm12_v := (others => ci_instr16_i(12)); -- sign extension
imm12_v(00):= '0';
imm12_v(01):= ci_instr16_i(3);
imm12_v(02):= ci_instr16_i(4);
imm12_v(03):= ci_instr16_i(10);
imm12_v(04):= ci_instr16_i(11);
imm12_v(05):= ci_instr16_i(2);
imm12_v(06):= ci_instr16_i(5);
imm12_v(07):= ci_instr16_i(6);
imm12_v(08):= ci_instr16_i(12);
-- actual decoder --
case ci_instr16_i(ci_opcode_msb_c downto ci_opcode_lsb_c) is
when "00" => -- C0: Register-Based Loads and Stores
case ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) is
when "000" => -- Illegal_instruction, C.ADDI4SPN
-- ----------------------------------------------------------------------------------------------------------
-- C.ADDI4SPN
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c);
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c) <= (others => '0'); -- zero extend
ci_instr32_o(instr_imm12_lsb_c + 0) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 1) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(6);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(11);
ci_instr32_o(instr_imm12_lsb_c + 5) <= ci_instr16_i(12);
ci_instr32_o(instr_imm12_lsb_c + 6) <= ci_instr16_i(7);
ci_instr32_o(instr_imm12_lsb_c + 7) <= ci_instr16_i(8);
ci_instr32_o(instr_imm12_lsb_c + 8) <= ci_instr16_i(9);
ci_instr32_o(instr_imm12_lsb_c + 9) <= ci_instr16_i(10);
--
ci_illegal_o <= not or_reduce_f(ci_instr16_i(12 downto 2)); -- 12:2 = "00000000000" is official illegal instruction
when "010" | "011" => -- C.LW / C.FLW
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c;
ci_instr32_o(21 downto 20) <= "00";
ci_instr32_o(22) <= ci_instr16_i(6);
ci_instr32_o(23) <= ci_instr16_i(10);
ci_instr32_o(24) <= ci_instr16_i(11);
ci_instr32_o(25) <= ci_instr16_i(12);
ci_instr32_o(26) <= ci_instr16_i(5);
ci_instr32_o(31 downto 27) <= (others => '0');
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_lw_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c); -- x8 - x15
if (ci_instr16_i(ci_funct3_lsb_c) = '1') then -- C.FLW
ci_illegal_o <= '1';
end if;
when "110" | "111" => -- C.SW / C.FSW
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c;
ci_instr32_o(08 downto 07) <= "00";
ci_instr32_o(09) <= ci_instr16_i(6);
ci_instr32_o(10) <= ci_instr16_i(10);
ci_instr32_o(11) <= ci_instr16_i(11);
ci_instr32_o(25) <= ci_instr16_i(12);
ci_instr32_o(26) <= ci_instr16_i(5);
ci_instr32_o(31 downto 27) <= (others => '0');
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sw_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= "01" & ci_instr16_i(ci_rs2_3_msb_c downto ci_rs2_3_lsb_c); -- x8 - x15
if (ci_instr16_i(ci_funct3_lsb_c) = '1') then -- C.FSW
ci_illegal_o <= '1';
end if;
when others => -- undefined
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o <= (others => '-');
ci_illegal_o <= '1';
end case;
when "01" => -- C1: Control Transfer Instructions, Integer Constant-Generation Instructions
case ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) is
when "101" => -- C.J
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_jal_c;
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "00000"; -- discard return address
ci_instr32_o(19 downto 12) <= imm20_v(19 downto 12);
ci_instr32_o(20) <= imm20_v(11);
ci_instr32_o(30 downto 21) <= imm20_v(10 downto 01);
ci_instr32_o(31) <= imm20_v(20);
when "001" => -- C.JAL
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_jal_c;
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "00001"; -- save return address to link register
ci_instr32_o(19 downto 12) <= imm20_v(19 downto 12);
ci_instr32_o(20) <= imm20_v(11);
ci_instr32_o(30 downto 21) <= imm20_v(10 downto 01);
ci_instr32_o(31) <= imm20_v(20);
when "110" => -- C.BEQ
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_branch_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_beq_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= "00000"; -- x0
ci_instr32_o(07) <= imm12_v(11);
ci_instr32_o(11 downto 08) <= imm12_v(04 downto 01);
ci_instr32_o(30 downto 25) <= imm12_v(10 downto 05);
ci_instr32_o(31) <= imm12_v(12);
when "111" => -- C.BNEZ
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_branch_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_bne_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= "00000"; -- x0
ci_instr32_o(07) <= imm12_v(11);
ci_instr32_o(11 downto 08) <= imm12_v(04 downto 01);
ci_instr32_o(30 downto 25) <= imm12_v(10 downto 05);
ci_instr32_o(31) <= imm12_v(12);
when "010" => -- C.LI
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00000"; -- x0
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c) <= (others => ci_instr16_i(12)); -- sign extend
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_instr32_o(instr_imm12_lsb_c + 5) <= ci_instr16_i(12);
when "011" => -- C.LUI / C.ADDI16SP
-- ----------------------------------------------------------------------------------------------------------
if (ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c) = "00010") then -- C.ADDI16SP
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "00010"; -- stack pointer
ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c) <= (others => ci_instr16_i(12)); -- sign extend
ci_instr32_o(instr_imm12_lsb_c + 0) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 1) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 2) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 3) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_instr32_o(instr_imm12_lsb_c + 5) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 6) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 7) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 8) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 9) <= ci_instr16_i(12);
else -- C.LUI
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_lui_c;
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
ci_instr32_o(instr_imm20_msb_c downto instr_imm20_lsb_c) <= (others => ci_instr16_i(12)); -- sign extend
ci_instr32_o(instr_imm20_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm20_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm20_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm20_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm20_lsb_c + 4) <= ci_instr16_i(6);
ci_instr32_o(instr_imm20_lsb_c + 5) <= ci_instr16_i(12);
end if;
if (ci_instr16_i(6 downto 2) = "00000") and (ci_instr16_i(12) = '0') then -- reserved
ci_illegal_o <= '1';
end if;
when "000" => -- C.NOP (rd=0) / C.ADDI
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c) <= (others => ci_instr16_i(12)); -- sign extend
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_instr32_o(instr_imm12_lsb_c + 5) <= ci_instr16_i(12);
when "100" => -- C.SRLI, C.SRAI, C.ANDI, C.SUB, C.XOR, C.OR, C.AND, reserved
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
if (ci_instr16_i(11 downto 10) = "11") then -- register-register operation
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alu_c;
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= "01" & ci_instr16_i(ci_rs2_3_msb_c downto ci_rs2_3_lsb_c);
case ci_instr16_i(6 downto 5) is
when "00" => -- C.SUB
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0100000";
when "01" => -- C.XOR
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_xor_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
when "10" => -- C.OR
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_or_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
when others => -- C.AND
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_and_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
end case;
else -- register-immediate operation
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
case ci_instr16_i(11 downto 10) is
when "00" => -- C.SRLI
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sr_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_illegal_o <= ci_instr16_i(12);
when "01" => -- C.SRAI
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sr_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0100000";
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_illegal_o <= ci_instr16_i(12);
when "10" => -- C.ANDI
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_and_c;
ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c) <= (others => ci_instr16_i(12)); -- sign extend
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_instr32_o(instr_imm12_lsb_c + 5) <= ci_instr16_i(12);
when others => -- register-register operation
NULL;
end case;
end if;
if (ci_instr16_i(12 downto 10) = "111") then -- reserved / undefined
ci_illegal_o <= '1';
end if;
when others => -- undefined
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o <= (others => '-');
ci_illegal_o <= '1';
end case;
when "10" => -- C2: Stack-Pointer-Based Loads and Stores, Control Transfer Instructions
case ci_instr16_i(ci_funct3_msb_c downto ci_funct3_lsb_c) is
when "000" => -- C.SLLI
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sll_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_illegal_o <= ci_instr16_i(12);
when "010" | "011" => -- C.LWSP / C.FLWSP
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c;
ci_instr32_o(21 downto 20) <= "00";
ci_instr32_o(22) <= ci_instr16_i(4);
ci_instr32_o(23) <= ci_instr16_i(5);
ci_instr32_o(24) <= ci_instr16_i(6);
ci_instr32_o(25) <= ci_instr16_i(12);
ci_instr32_o(26) <= ci_instr16_i(2);
ci_instr32_o(27) <= ci_instr16_i(3);
ci_instr32_o(31 downto 28) <= (others => '0');
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_lw_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
if (ci_instr16_i(ci_funct3_lsb_c) = '1') then -- C.FLWSP
ci_illegal_o <= '1';
end if;
when "110" | "111" => -- C.SWSP / C.FSWSP
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c;
ci_instr32_o(08 downto 07) <= "00";
ci_instr32_o(09) <= ci_instr16_i(9);
ci_instr32_o(10) <= ci_instr16_i(10);
ci_instr32_o(11) <= ci_instr16_i(11);
ci_instr32_o(25) <= ci_instr16_i(12);
ci_instr32_o(26) <= ci_instr16_i(7);
ci_instr32_o(27) <= ci_instr16_i(8);
ci_instr32_o(31 downto 28) <= (others => '0');
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sw_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= ci_instr16_i(ci_rs2_5_msb_c downto ci_rs2_5_lsb_c);
if (ci_instr16_i(ci_funct3_lsb_c) = '1') then -- C.FSWSP
ci_illegal_o <= '1';
end if;
when "100" => -- C.JR, C.JALR, C.MV, C.EBREAK, C.ADD
-- ----------------------------------------------------------------------------------------------------------
if (ci_instr16_i(12) = '0') then -- C.JR, C.MV
if (ci_instr16_i(6 downto 2) = "00000") then -- C.JR
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_jalr_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "00000"; -- discard return address
else -- C.MV
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alu_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= "000";
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00000"; -- x0
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= ci_instr16_i(ci_rs2_5_msb_c downto ci_rs2_5_lsb_c);
end if;
else -- C.EBREAK, C.JALR, C.ADD
if (ci_instr16_i(6 downto 2) = "00000") then -- C.EBREAK, C.JALR
if (ci_instr16_i(11 downto 7) = "00000") then -- C.EBREAK
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_syscsr_c;
ci_instr32_o(instr_funct12_msb_c downto instr_funct12_lsb_c) <= "000000000001";
else -- C.JALR
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_jalr_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= ci_instr16_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "00001"; -- save return address to link register
end if;
else -- C.ADD
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alu_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= "000";
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= ci_instr16_i(ci_rs2_5_msb_c downto ci_rs2_5_lsb_c);
end if;
end if;
when others => -- undefined
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o <= (others => '-');
ci_illegal_o <= '1';
end case;
when others => -- not a compressed instruction
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o <= (others => '-');
ci_illegal_o <= '0';
end case;
end process decompressor;
end neorv32_cpu_decompressor_rtl;

View File

@ -0,0 +1,135 @@
-- #################################################################################################
-- # << NEORV32 - CPU General Purpose Data Register File >> #
-- # ********************************************************************************************* #
-- # General purpose data register file. 32 entries (= 1024 bit) for normal mode (RV32I), #
-- # 16 entries (= 512 bit) for embedded mode (RV32E) when RISC-V "E" extension is enabled. #
-- # #
-- # Register zero (r0/x0) is a "normal" physical register that has to be initialized to zero by #
-- # the early boot code. Register zero is always set to zero when written. #
-- # #
-- # The register file uses synchronous read accesses and a *single* (multiplexed) address port #
-- # for writing and reading rd/rs1 and a single read-only port for rs2. Therefore, the whole #
-- # register file can be mapped to a single true-dual-port block RAM. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_cpu_regfile is
generic (
CPU_EXTENSION_RISCV_E : boolean -- implement embedded RF extension?
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
-- data input --
mem_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory read data
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
-- data output --
rs1_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operand 1
rs2_o : out std_ulogic_vector(data_width_c-1 downto 0) -- operand 2
);
end neorv32_cpu_regfile;
architecture neorv32_cpu_regfile_rtl of neorv32_cpu_regfile is
-- register file --
type reg_file_t is array (31 downto 0) of std_ulogic_vector(data_width_c-1 downto 0);
type reg_file_emb_t is array (15 downto 0) of std_ulogic_vector(data_width_c-1 downto 0);
signal reg_file : reg_file_t;
signal reg_file_emb : reg_file_emb_t;
signal rf_wdata : std_ulogic_vector(data_width_c-1 downto 0); -- actual write-back data
signal rd_is_r0 : std_ulogic; -- writing to r0?
signal dst_addr : std_ulogic_vector(4 downto 0); -- destination address
signal opa_addr : std_ulogic_vector(4 downto 0); -- rs1/dst address
signal opb_addr : std_ulogic_vector(4 downto 0); -- rs2 address
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- read data
begin
-- Data Input Mux -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
input_mux: process(rd_is_r0, ctrl_i, alu_i, mem_i)
begin
if (rd_is_r0 = '1') then -- write zero if accessing x0 to "emulate" it is hardwired to zero
rf_wdata <= (others => '0');
else
if (ctrl_i(ctrl_rf_in_mux_c) = '0') then
rf_wdata <= alu_i;
else
rf_wdata <= mem_i;
end if;
end if;
end process input_mux;
-- check if we are writing to x0 --
rd_is_r0 <= (not or_reduce_f(dst_addr(4 downto 0))) when (CPU_EXTENSION_RISCV_E = false) else (not or_reduce_f(dst_addr(3 downto 0)));
-- Register File Access -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rf_access: process(clk_i)
begin
if rising_edge(clk_i) then -- sync read and write
if (CPU_EXTENSION_RISCV_E = false) then -- normal register file with 32 entries
if (ctrl_i(ctrl_rf_wb_en_c) = '1') then
reg_file(to_integer(unsigned(opa_addr(4 downto 0)))) <= rf_wdata;
end if;
rs1 <= reg_file(to_integer(unsigned(opa_addr(4 downto 0))));
rs2 <= reg_file(to_integer(unsigned(opb_addr(4 downto 0))));
else -- embedded register file with 16 entries
if (ctrl_i(ctrl_rf_wb_en_c) = '1') then
reg_file_emb(to_integer(unsigned(opa_addr(3 downto 0)))) <= rf_wdata;
end if;
rs1 <= reg_file_emb(to_integer(unsigned(opa_addr(3 downto 0))));
rs2 <= reg_file_emb(to_integer(unsigned(opb_addr(3 downto 0))));
end if;
end if;
end process rf_access;
-- access addresses --
dst_addr <= ctrl_i(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c);
opa_addr <= dst_addr when (ctrl_i(ctrl_rf_wb_en_c) = '1') else ctrl_i(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c); -- rd/rs1
opb_addr <= ctrl_i(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c); -- rs2
-- data output --
rs1_o <= rs1;
rs2_o <= rs2;
end neorv32_cpu_regfile_rtl;

View File

@ -0,0 +1,728 @@
-- #################################################################################################
-- # << NEORV32 - RISC-V-Compatible Debug Module (DM) >> #
-- # ********************************************************************************************* #
-- # Compatible to the "Minimal RISC-V External Debug Spec. Version 0.13.2" #
-- # -> "Execution-based" debugging scheme #
-- # ********************************************************************************************* #
-- # Key features: #
-- # * register access commands only #
-- # * auto-execution commands #
-- # * for a single hart only #
-- # * 2 general purpose program buffer entries #
-- # * 1 general purpose data buffer entry #
-- # #
-- # CPU access: #
-- # * ROM for "park loop" code #
-- # * program buffer #
-- # * data buffer #
-- # * control and status register #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_debug_dm is
port (
-- global control --
clk_i : in std_ulogic; -- global clock line
rstn_i : in std_ulogic; -- global reset line, low-active
-- debug module interface (DMI) --
dmi_rstn_i : in std_ulogic;
dmi_req_valid_i : in std_ulogic;
dmi_req_ready_o : out std_ulogic; -- DMI is allowed to make new requests when set
dmi_req_addr_i : in std_ulogic_vector(06 downto 0);
dmi_req_op_i : in std_ulogic; -- 0=read, 1=write
dmi_req_data_i : in std_ulogic_vector(31 downto 0);
dmi_resp_valid_o : out std_ulogic; -- response valid when set
dmi_resp_ready_i : in std_ulogic; -- ready to receive respond
dmi_resp_data_o : out std_ulogic_vector(31 downto 0);
dmi_resp_err_o : out std_ulogic; -- 0=ok, 1=error
-- CPU bus access --
cpu_addr_i : in std_ulogic_vector(31 downto 0); -- address
cpu_rden_i : in std_ulogic; -- read enable
cpu_wren_i : in std_ulogic; -- write enable
cpu_data_i : in std_ulogic_vector(31 downto 0); -- data in
cpu_data_o : out std_ulogic_vector(31 downto 0); -- data out
cpu_ack_o : out std_ulogic; -- transfer acknowledge
-- CPU control --
cpu_ndmrstn_o : out std_ulogic; -- soc reset
cpu_halt_req_o : out std_ulogic -- request hart to halt (enter debug mode)
);
end neorv32_debug_dm;
architecture neorv32_debug_dm_rtl of neorv32_debug_dm is
-- DM configuration --
constant nscratch_c : std_ulogic_vector(03 downto 0) := "0001"; -- number of dscratch* registers in CPU = 1
constant dataaccess_c : std_ulogic := '1'; -- 1: abstract data is memory-mapped, 0: abstract data is CSR-mapped
constant datasize_c : std_ulogic_vector(03 downto 0) := "0001"; -- number of data registers in memory/CSR space = 1
constant dataaddr_c : std_ulogic_vector(11 downto 0) := dm_data_base_c(11 downto 0); -- signed base address of data registers in memory/CSR space
-- available DMI registers --
constant addr_data0_c : std_ulogic_vector(6 downto 0) := "000" & x"4";
constant addr_dmcontrol_c : std_ulogic_vector(6 downto 0) := "001" & x"0";
constant addr_dmstatus_c : std_ulogic_vector(6 downto 0) := "001" & x"1";
constant addr_hartinfo_c : std_ulogic_vector(6 downto 0) := "001" & x"2";
constant addr_abstractcs_c : std_ulogic_vector(6 downto 0) := "001" & x"6";
constant addr_command_c : std_ulogic_vector(6 downto 0) := "001" & x"7";
constant addr_abstractauto_c : std_ulogic_vector(6 downto 0) := "001" & x"8";
constant addr_nextdm_c : std_ulogic_vector(6 downto 0) := "001" & x"d";
constant addr_progbuf0_c : std_ulogic_vector(6 downto 0) := "010" & x"0";
constant addr_progbuf1_c : std_ulogic_vector(6 downto 0) := "010" & x"1";
constant addr_sbcs_c : std_ulogic_vector(6 downto 0) := "011" & x"8";
constant addr_haltsum0_c : std_ulogic_vector(6 downto 0) := "100" & x"0";
-- RISC-V 32-bit instruction prototypes --
constant instr_nop_c : std_ulogic_vector(31 downto 0) := x"00000013"; -- nop
constant instr_lw_c : std_ulogic_vector(31 downto 0) := x"00002003"; -- lw zero, 0(zero)
constant instr_sw_c : std_ulogic_vector(31 downto 0) := x"00002023"; -- sw zero, 0(zero)
constant instr_ebreak_c : std_ulogic_vector(31 downto 0) := x"00100073"; -- ebreak
-- debug module controller --
type dm_ctrl_state_t is (CMD_IDLE, CMD_EXE_CHECK, CMD_EXE_PREPARE, CMD_EXE_TRIGGER, CMD_EXE_BUSY, CMD_EXE_ERROR);
type dm_ctrl_t is record
-- fsm --
state : dm_ctrl_state_t;
busy : std_ulogic;
ldsw_progbuf : std_ulogic_vector(31 downto 0);
pbuf_en : std_ulogic;
-- error flags --
illegal_state : std_ulogic;
illegal_cmd : std_ulogic;
cmderr : std_ulogic_vector(02 downto 0);
-- hart status --
hart_halted : std_ulogic;
hart_resume_req : std_ulogic;
hart_resume_ack : std_ulogic;
hart_reset : std_ulogic;
end record;
signal dm_ctrl : dm_ctrl_t;
-- debug module DMI registers / access --
type progbuf_t is array (0 to 1) of std_ulogic_vector(31 downto 0);
type dm_reg_t is record
dmcontrol_ndmreset : std_ulogic;
dmcontrol_dmactive : std_ulogic;
abstractauto_autoexecdata : std_ulogic;
abstractauto_autoexecprogbuf : std_ulogic_vector(01 downto 0);
progbuf : progbuf_t;
command : std_ulogic_vector(31 downto 0);
--
halt_req : std_ulogic;
resume_req : std_ulogic;
reset_ack : std_ulogic;
wr_acc_err : std_ulogic;
rd_acc_err : std_ulogic;
clr_acc_err : std_ulogic;
autoexec_wr : std_ulogic;
autoexec_rd : std_ulogic;
end record;
signal dm_reg : dm_reg_t;
-- cpu program buffer --
type cpu_progbuf_t is array (0 to 4) of std_ulogic_vector(31 downto 0);
signal cpu_progbuf : cpu_progbuf_t;
-- **********************************************************
-- CPU Bus Interface
-- **********************************************************
-- 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
resume_ack : std_ulogic; -- CPU starts resuming when set (single-shot)
execute_req : std_ulogic; -- DM wants CPU to execute program buffer when set
execute_ack : std_ulogic; -- CPU starts executing program buffer when set (single-shot)
exception_ack : std_ulogic; -- CPU has detected an exception (single-shot)
progbuf : std_ulogic_vector(255 downto 0); -- program buffer, 4 32-bit entries
data_we : std_ulogic; -- write abstract data
wdata : std_ulogic_vector(31 downto 0); -- abstract write data
rdata : std_ulogic_vector(31 downto 0); -- abstract read data
end record;
signal dci : dci_t;
-- 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 --
constant sreg_halt_ack_c : natural := 0; -- -/w: CPU is halted in debug mode and waits in park loop
constant sreg_resume_req_c : natural := 1; -- r/-: DM requests CPU to resume
constant sreg_resume_ack_c : natural := 2; -- -/w: CPU starts resuming
constant sreg_execute_req_c : natural := 3; -- r/-: DM requests to execute program buffer
constant sreg_execute_ack_c : natural := 4; -- -/w: CPU starts to execute program buffer
constant sreg_exception_ack_c : natural := 5; -- -/w: CPU has detected an exception
-- code ROM containing "park loop" --
type code_rom_file_t is array (0 to 31) of std_ulogic_vector(31 downto 0);
constant code_rom_file : code_rom_file_t := (
00000000 => x"0180006f",
00000001 => x"7b241073",
00000002 => x"02000413",
00000003 => x"98802023",
00000004 => x"7b202473",
00000005 => x"00100073",
00000006 => x"7b241073",
00000007 => x"00100413",
00000008 => x"98802023",
00000009 => x"98002403",
00000010 => x"00847413",
00000011 => x"02041263",
00000012 => x"98002403",
00000013 => x"00247413",
00000014 => x"00041463",
00000015 => x"fe9ff06f",
00000016 => x"00400413",
00000017 => x"98802023",
00000018 => x"7b202473",
00000019 => x"7b200073",
00000020 => x"01000413",
00000021 => x"98802023",
00000022 => x"7b202473",
00000023 => x"0000100f",
00000024 => x"88000067",
others => x"00100073" -- ebreak
);
-- 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);
-- program buffer access --
type prog_buf_t is array (0 to 3) of std_ulogic_vector(31 downto 0);
signal prog_buf : prog_buf_t;
begin
-- Debug Module Command Controller --------------------------------------------------------
-- -------------------------------------------------------------------------------------------
dm_controller: process(clk_i)
begin
if rising_edge(clk_i) then
if (dm_reg.dmcontrol_dmactive = '0') or (dmi_rstn_i = '0') then -- DM reset / DM disabled
dm_ctrl.state <= CMD_IDLE;
dm_ctrl.ldsw_progbuf <= (others => '-');
dci.execute_req <= '0';
dm_ctrl.pbuf_en <= '-';
--
dm_ctrl.illegal_cmd <= '-';
dm_ctrl.illegal_state <= '-';
dm_ctrl.cmderr <= "000";
--
dm_ctrl.hart_reset <= '0';
dm_ctrl.hart_halted <= '0';
dm_ctrl.hart_resume_req <= '0';
dm_ctrl.hart_resume_ack <= '0';
else -- DM active
-- defaults --
dci.execute_req <= '0';
dm_ctrl.illegal_cmd <= '0';
dm_ctrl.illegal_state <= '0';
-- command execution fsm --
case dm_ctrl.state is
when CMD_IDLE => -- wait for new abstract command
-- ------------------------------------------------------------
if (dmi_req_valid_i = '1') and (dmi_req_op_i = '1') then -- valid DM write access
if (dmi_req_addr_i = addr_command_c) then
if (dm_ctrl.cmderr = "000") then -- only execute if no error
dm_ctrl.state <= CMD_EXE_CHECK;
end if;
end if;
elsif (dm_reg.autoexec_rd = '1') or (dm_reg.autoexec_wr = '1') then -- auto execution trigger
dm_ctrl.state <= CMD_EXE_CHECK;
end if;
when CMD_EXE_CHECK => -- check if command is valid / supported
-- ------------------------------------------------------------
if (dm_reg.command(31 downto 24) = x"00") and -- cmdtype: register access
(dm_reg.command(23) = '0') and -- reserved
(dm_reg.command(22 downto 20) = "010") and -- aarsize: has to be 32-bit
(dm_reg.command(19) = '0') and -- aarpostincrement: not supported
((dm_reg.command(17) = '0') or (dm_reg.command(15 downto 05) = "00010000000")) then -- regno: only GPRs are supported: 0x1000..0x101f if transfer is set
if (dm_ctrl.hart_halted = '1') then -- CPU is halted
dm_ctrl.state <= CMD_EXE_PREPARE;
else -- error! CPU is still running
dm_ctrl.illegal_state <= '1';
dm_ctrl.state <= CMD_EXE_ERROR;
end if;
else -- invalid command
dm_ctrl.illegal_cmd <= '1';
dm_ctrl.state <= CMD_EXE_ERROR;
end if;
when CMD_EXE_PREPARE => -- setup program buffer
-- ------------------------------------------------------------
if (dm_reg.command(17) = '1') then -- "transfer"
if (dm_reg.command(16) = '0') then -- "write" = 0 -> read from GPR
dm_ctrl.ldsw_progbuf <= instr_sw_c;
dm_ctrl.ldsw_progbuf(31 downto 25) <= dataaddr_c(11 downto 05); -- destination address
dm_ctrl.ldsw_progbuf(24 downto 20) <= dm_reg.command(4 downto 0); -- "regno" = source register
dm_ctrl.ldsw_progbuf(11 downto 07) <= dataaddr_c(04 downto 00); -- destination address
else -- "write" = 0 -> 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(11 downto 07) <= dm_reg.command(4 downto 0); -- "regno" = destination register
end if;
else
dm_ctrl.ldsw_progbuf <= instr_nop_c; -- NOP - do nothing
end if;
--
if (dm_reg.command(18) = '1') then -- "postexec" - execute program buffer
dm_ctrl.pbuf_en <= '1';
else -- execute all program buffer entries as NOPs
dm_ctrl.pbuf_en <= '0';
end if;
--
dm_ctrl.state <= CMD_EXE_TRIGGER;
when CMD_EXE_TRIGGER => -- request CPU to execute command
-- ------------------------------------------------------------
dci.execute_req <= '1'; -- request execution
if (dci.execute_ack = '1') then -- CPU starts execution
dm_ctrl.state <= CMD_EXE_BUSY;
end if;
when CMD_EXE_BUSY => -- wait for CPU to finish
-- ------------------------------------------------------------
if (dci.halt_ack = '1') then -- CPU is parked (halted) again -> execution done
dm_ctrl.state <= CMD_IDLE;
end if;
when CMD_EXE_ERROR => -- delay cycle for error to arrive abstracts.cmderr
-- ------------------------------------------------------------
dm_ctrl.state <= CMD_IDLE;
when others => -- undefined
-- ------------------------------------------------------------
dm_ctrl.state <= CMD_IDLE;
end case;
-- error flags --
-- ------------------------------------------------------------
if (dm_ctrl.cmderr = "000") then -- set new error
if (dm_ctrl.illegal_state = '1') then -- cannot execute since hart is not in expected state
dm_ctrl.cmderr <= "100";
elsif (dci.exception_ack = '1') then -- exception during execution
dm_ctrl.cmderr <= "011";
elsif (dm_ctrl.illegal_cmd = '1') then -- unsupported command
dm_ctrl.cmderr <= "010";
elsif (dm_reg.rd_acc_err = '1') or (dm_reg.wr_acc_err = '1') then -- invalid read/write while command is executing
dm_ctrl.cmderr <= "001";
end if;
elsif (dm_reg.clr_acc_err = '1') then -- acknowledge/clear error flags
dm_ctrl.cmderr <= "000";
end if;
-- hart status --
-- ------------------------------------------------------------
-- HALTED --
if (dm_reg.dmcontrol_ndmreset = '1') then
dm_ctrl.hart_halted <= '0';
elsif (dci.halt_ack = '1') then
dm_ctrl.hart_halted <= '1';
elsif (dci.resume_ack = '1') then
dm_ctrl.hart_halted <= '0';
end if;
-- RESUME REQ --
if (dm_reg.dmcontrol_ndmreset = '1') then
dm_ctrl.hart_resume_req <= '0';
elsif (dm_reg.resume_req = '1') then
dm_ctrl.hart_resume_req <= '1';
elsif (dci.resume_ack = '1') then
dm_ctrl.hart_resume_req <= '0';
end if;
-- RESUME ACK --
if (dm_reg.dmcontrol_ndmreset = '1') then
dm_ctrl.hart_resume_ack <= '0';
elsif (dci.resume_ack = '1') then
dm_ctrl.hart_resume_ack <= '1';
elsif (dm_reg.resume_req = '1') then
dm_ctrl.hart_resume_ack <= '0';
end if;
-- hart has been RESET --
if (dm_reg.dmcontrol_ndmreset = '1') then
dm_ctrl.hart_reset <= '1';
elsif (dm_reg.reset_ack = '1') then
dm_ctrl.hart_reset <= '0';
end if;
end if;
end if;
end process dm_controller;
-- controller busy flag --
dm_ctrl.busy <= '0' when (dm_ctrl.state = CMD_IDLE) else '1';
-- Debug Module Interface - Write Access --------------------------------------------------
-- -------------------------------------------------------------------------------------------
dmi_write_access: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
dm_reg.dmcontrol_ndmreset <= '0';
dm_reg.dmcontrol_dmactive <= '0'; -- DM is in reset state after hardware reset
--
dm_reg.abstractauto_autoexecdata <= '0';
dm_reg.abstractauto_autoexecprogbuf <= "00";
--
dm_reg.command <= (others => '0');
dm_reg.progbuf <= (others => instr_nop_c);
--
dm_reg.halt_req <= '0';
dm_reg.resume_req <= '0';
dm_reg.reset_ack <= '0';
dm_reg.wr_acc_err <= '0';
dm_reg.clr_acc_err <= '0';
dm_reg.autoexec_wr <= '0';
elsif rising_edge(clk_i) then
-- default --
dm_reg.resume_req <= '0';
dm_reg.reset_ack <= '0';
dm_reg.wr_acc_err <= '0';
dm_reg.clr_acc_err <= '0';
dm_reg.autoexec_wr <= '0';
-- DMI access --
if (dmi_req_valid_i = '1') and (dmi_req_op_i = '1') then -- valid DMI write request
-- debug module control --
if (dmi_req_addr_i = addr_dmcontrol_c) then
dm_reg.halt_req <= dmi_req_data_i(31); -- haltreq (-/w): write 1 to request halt; has to be cleared again by debugger
dm_reg.resume_req <= dmi_req_data_i(30); -- resumereq (-/w1): write 1 to request resume
dm_reg.reset_ack <= dmi_req_data_i(28); -- ackhavereset (-/w1)
dm_reg.dmcontrol_ndmreset <= dmi_req_data_i(01); -- ndmreset (r/w): soc reset
dm_reg.dmcontrol_dmactive <= dmi_req_data_i(00); -- dmactive (r/w): DM reset
end if;
-- write abstract command --
if (dmi_req_addr_i = addr_command_c) then
if (dm_ctrl.busy = '0') and (dm_ctrl.cmderr = "000") then -- idle and no errors yet
dm_reg.command <= dmi_req_data_i;
end if;
end if;
-- write abstract command autoexec --
if (dmi_req_addr_i = addr_abstractauto_c) then
if (dm_ctrl.busy = '0') then -- idle and no errors yet
dm_reg.abstractauto_autoexecdata <= dmi_req_data_i(00);
dm_reg.abstractauto_autoexecprogbuf(0) <= dmi_req_data_i(16);
dm_reg.abstractauto_autoexecprogbuf(1) <= dmi_req_data_i(17);
end if;
end if;
-- auto execution trigger --
if ((dmi_req_addr_i = addr_data0_c) and (dm_reg.abstractauto_autoexecdata = '1')) or
((dmi_req_addr_i = addr_progbuf0_c) and (dm_reg.abstractauto_autoexecprogbuf(0) = '1')) or
((dmi_req_addr_i = addr_progbuf1_c) and (dm_reg.abstractauto_autoexecprogbuf(1) = '1')) then
dm_reg.autoexec_wr <= '1';
end if;
-- acknowledge command error --
if (dmi_req_addr_i = addr_abstractcs_c) then
if (dmi_req_data_i(10 downto 8) = "111") then
dm_reg.clr_acc_err <= '1';
end if;
end if;
-- write program buffer --
if (dmi_req_addr_i(dmi_req_addr_i'left downto 1) = addr_progbuf0_c(dmi_req_addr_i'left downto 1)) then
if (dm_ctrl.busy = '0') then -- idle
if (dmi_req_addr_i(0) = addr_progbuf0_c(0)) then
dm_reg.progbuf(0) <= dmi_req_data_i;
else
dm_reg.progbuf(1) <= dmi_req_data_i;
end if;
end if;
end if;
-- invalid access (while command is executing) --
if (dm_ctrl.busy = '1') then -- busy
if (dmi_req_addr_i = addr_abstractcs_c) or
(dmi_req_addr_i = addr_command_c) or
(dmi_req_addr_i = addr_abstractauto_c) or
(dmi_req_addr_i = addr_data0_c) or
(dmi_req_addr_i = addr_progbuf0_c) or
(dmi_req_addr_i = addr_progbuf1_c) then
dm_reg.wr_acc_err <= '1';
end if;
end if;
end if;
end if;
end process dmi_write_access;
-- Direct Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- write to abstract data register --
dci.data_we <= '1' when (dmi_req_valid_i = '1') and (dmi_req_op_i = '1') and (dmi_req_addr_i = addr_data0_c) and (dm_ctrl.busy = '0') else '0';
dci.wdata <= dmi_req_data_i;
-- CPU halt/resume request --
cpu_halt_req_o <= dm_reg.halt_req and dm_reg.dmcontrol_dmactive; -- single shot
dci.resume_req <= dm_ctrl.hart_resume_req; -- permanent
-- SoC reset --
cpu_ndmrstn_o <= not (dm_reg.dmcontrol_ndmreset and dm_reg.dmcontrol_dmactive);
-- build program buffer array for cpu access --
cpu_progbuf(0) <= dm_ctrl.ldsw_progbuf; -- pseudo program buffer for GPR access
cpu_progbuf(1) <= instr_nop_c when (dm_ctrl.pbuf_en = '0') else dm_reg.progbuf(0);
cpu_progbuf(2) <= instr_nop_c when (dm_ctrl.pbuf_en = '0') else dm_reg.progbuf(1);
cpu_progbuf(3) <= instr_ebreak_c; -- implicit ebreak instruction
-- DMI status --
dmi_resp_err_o <= '0'; -- what can go wrong?
dmi_req_ready_o <= '1'; -- always ready for new read/write accesses
-- Debug Module Interface - Read Access ---------------------------------------------------
-- -------------------------------------------------------------------------------------------
dmi_read_access: process(clk_i)
begin
if rising_edge(clk_i) then
dmi_resp_valid_o <= dmi_req_valid_i; -- DMI transfer ack
dmi_resp_data_o <= (others => '0'); -- default
dm_reg.rd_acc_err <= '0';
dm_reg.autoexec_rd <= '0';
case dmi_req_addr_i is
-- debug module status register --
when addr_dmstatus_c =>
dmi_resp_data_o(31 downto 23) <= (others => '0'); -- reserved (r/-)
dmi_resp_data_o(22) <= '1'; -- impebreak (r/-): there is an implicit ebreak instruction after the visible program buffer
dmi_resp_data_o(21 downto 20) <= (others => '0'); -- reserved (r/-)
dmi_resp_data_o(19) <= dm_ctrl.hart_reset; -- allhavereset (r/-): there is only one hart that can be reset
dmi_resp_data_o(18) <= dm_ctrl.hart_reset; -- anyhavereset (r/-): there is only one hart that can be reset
dmi_resp_data_o(17) <= dm_ctrl.hart_resume_ack; -- allresumeack (r/-): there is only one hart that can acknowledge resume request
dmi_resp_data_o(16) <= dm_ctrl.hart_resume_ack; -- anyresumeack (r/-): there is only one hart that can acknowledge resume request
dmi_resp_data_o(15) <= '0'; -- allnonexistent (r/-): there is only one hart that is always existent
dmi_resp_data_o(14) <= '0'; -- anynonexistent (r/-): there is only one hart that is always existent
dmi_resp_data_o(13) <= dm_reg.dmcontrol_ndmreset; -- allunavail (r/-): there is only one hart that is unavailable during reset
dmi_resp_data_o(12) <= dm_reg.dmcontrol_ndmreset; -- anyunavail (r/-): there is only one hart that is unavailable during reset
dmi_resp_data_o(11) <= not dm_ctrl.hart_halted; -- allrunning (r/-): there is only one hart that can be RUNNING or HALTED
dmi_resp_data_o(10) <= not dm_ctrl.hart_halted; -- anyrunning (r/-): there is only one hart that can be RUNNING or HALTED
dmi_resp_data_o(09) <= dm_ctrl.hart_halted; -- allhalted (r/-): there is only one hart that can be RUNNING or HALTED
dmi_resp_data_o(08) <= dm_ctrl.hart_halted; -- anyhalted (r/-): there is only one hart that can be RUNNING or HALTED
dmi_resp_data_o(07) <= '1'; -- authenticated (r/-): authentication passed since there is no authentication
dmi_resp_data_o(06) <= '0'; -- authbusy (r/-): always ready since there is no authentication
dmi_resp_data_o(05) <= '0'; -- hasresethaltreq (r/-): halt-on-reset not implemented
dmi_resp_data_o(04) <= '0'; -- confstrptrvalid (r/-): no configuration string available
dmi_resp_data_o(03 downto 00) <= "0010"; -- version (r/-): compatible to version 0.13
-- debug module control --
when addr_dmcontrol_c =>
dmi_resp_data_o(31) <= '0'; -- haltreq (-/w): write-only
dmi_resp_data_o(30) <= '0'; -- resumereq (-/w1): write-only
dmi_resp_data_o(29) <= '0'; -- hartreset (r/w): not supported
dmi_resp_data_o(28) <= '0'; -- ackhavereset (-/w1): write-only
dmi_resp_data_o(27) <= '0'; -- reserved (r/-)
dmi_resp_data_o(26) <= '0'; -- hasel (r/-) - there is a single currently selected hart
dmi_resp_data_o(25 downto 16) <= (others => '0'); -- hartsello (r/-) - there is only one hart
dmi_resp_data_o(15 downto 06) <= (others => '0'); -- hartselhi (r/-) - there is only one hart
dmi_resp_data_o(05 downto 04) <= (others => '0'); -- reserved (r/-)
dmi_resp_data_o(03) <= '0'; -- setresethaltreq (-/w1): halt-on-reset request - halt-on-reset not implemented
dmi_resp_data_o(02) <= '0'; -- clrresethaltreq (-/w1): halt-on-reset ack - halt-on-reset not implemented
dmi_resp_data_o(01) <= dm_reg.dmcontrol_ndmreset; -- ndmreset (r/w): soc reset
dmi_resp_data_o(00) <= dm_reg.dmcontrol_dmactive; -- dmactive (r/w): DM reset
-- hart info --
when addr_hartinfo_c =>
dmi_resp_data_o(31 downto 24) <= (others => '0'); -- reserved (r/-)
dmi_resp_data_o(23 downto 20) <= nscratch_c; -- nscratch (r/-): number of dscratch CSRs
dmi_resp_data_o(19 downto 17) <= (others => '0'); -- reserved (r/-)
dmi_resp_data_o(16) <= dataaccess_c; -- dataaccess (r/-): 1: data registers are memory-mapped, 0: data reisters are CSR-mapped
dmi_resp_data_o(15 downto 12) <= datasize_c; -- datasize (r/-): number data registers in memory/CSR space
dmi_resp_data_o(11 downto 00) <= dataaddr_c; -- dataaddr (r/-): data registers base address (memory/CSR)
-- abstract control and status --
when addr_abstractcs_c =>
dmi_resp_data_o(31 downto 24) <= (others => '0'); -- reserved (r/-)
dmi_resp_data_o(28 downto 24) <= "00010"; -- progbufsize (r/-): number of words in program buffer = 2
dmi_resp_data_o(12) <= dm_ctrl.busy; -- busy (r/-): abstract command in progress (1) / idle (0)
dmi_resp_data_o(11) <= '0'; -- reserved (r/-)
dmi_resp_data_o(10 downto 08) <= dm_ctrl.cmderr; -- cmderr (r/w1c): any error during execution?
dmi_resp_data_o(07 downto 04) <= (others => '0'); -- reserved (r/-)
dmi_resp_data_o(03 downto 00) <= "0001"; -- datacount (r/-): number of implemented data registers = 1
-- -- abstract command (-/w) --
-- when addr_command_c =>
-- dmi_resp_data_o <= (others => '0'); -- register is write-only
-- abstract command autoexec (r/w) --
when addr_abstractauto_c =>
dmi_resp_data_o(00) <= dm_reg.abstractauto_autoexecdata; -- autoexecdata(0): read/write access to data0 triggers execution of program buffer
dmi_resp_data_o(16) <= dm_reg.abstractauto_autoexecprogbuf(0); -- autoexecprogbuf(0): read/write access to progbuf0 triggers execution of program buffer
dmi_resp_data_o(17) <= dm_reg.abstractauto_autoexecprogbuf(1); -- autoexecprogbuf(1): read/write access to progbuf1 triggers execution of program buffer
-- -- next debug module (r/-) --
-- when addr_nextdm_c =>
-- dmi_resp_data_o <= (others => '0'); -- this is the only DM
-- abstract data 0 (r/w) --
when addr_data0_c =>
dmi_resp_data_o <= dci.rdata;
-- program buffer (r/w) --
when addr_progbuf0_c =>
dmi_resp_data_o <= dm_reg.progbuf(0); -- program buffer 0
when addr_progbuf1_c =>
dmi_resp_data_o <= dm_reg.progbuf(1); -- program buffer 1
-- -- system bus access control and status (r/-) --
-- when addr_sbcs_c =>
-- dmi_resp_data_o <= (others => '0'); -- bus access not implemented
-- halt summary 0 (r/-) --
when addr_haltsum0_c =>
dmi_resp_data_o(0) <= dm_ctrl.hart_halted; -- hart is halted
-- not implemented (r/-) --
when others =>
dmi_resp_data_o <= (others => '0');
end case;
-- invalid read access (while command is executing)
-- ------------------------------------------------------------
if (dmi_req_valid_i = '1') and (dmi_req_op_i = '0') then -- valid DMI read request
if (dm_ctrl.busy = '1') then -- busy
if (dmi_req_addr_i = addr_data0_c) or
(dmi_req_addr_i = addr_progbuf0_c) or
(dmi_req_addr_i = addr_progbuf1_c) then
dm_reg.rd_acc_err <= '1';
end if;
end if;
end if;
-- auto execution trigger --
-- ------------------------------------------------------------
if (dmi_req_valid_i = '1') and (dmi_req_op_i = '0') then -- valid DMI read request
if ((dmi_req_addr_i = addr_data0_c) and (dm_reg.abstractauto_autoexecdata = '1')) or
((dmi_req_addr_i = addr_progbuf0_c) and (dm_reg.abstractauto_autoexecprogbuf(0) = '1')) or
((dmi_req_addr_i = addr_progbuf1_c) and (dm_reg.abstractauto_autoexecprogbuf(1) = '1')) then
dm_reg.autoexec_rd <= '1';
end if;
end if;
end if;
end process dmi_read_access;
-- **************************************************************************************************************************
-- CPU Bus Interface
-- **************************************************************************************************************************
-- Access Control ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (cpu_addr_i(hi_abb_c downto lo_abb_c) = dm_base_c(hi_abb_c downto lo_abb_c)) else '0';
maddr <= cpu_addr_i(lo_abb_c-1 downto lo_abb_c-2); -- (sub-)module select address
rden <= acc_en and cpu_rden_i;
wren <= acc_en and cpu_wren_i;
-- Write Access ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
write_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- Data buffer --
if (dci.data_we = '1') then -- DM write access
data_buf <= dci.wdata;
elsif (acc_en = '1') and (maddr = "10") and (wren = '1') then -- BUS write access
data_buf <= cpu_data_i;
end if;
-- Control and Status Register --
dci.halt_ack <= '0'; -- all writable flags auto-clear
dci.resume_ack <= '0';
dci.execute_ack <= '0';
dci.exception_ack <= '0';
if (acc_en = '1') and (maddr = "11") and (wren = '1') then
dci.halt_ack <= cpu_data_i(sreg_halt_ack_c);
dci.resume_ack <= cpu_data_i(sreg_resume_ack_c);
dci.execute_ack <= cpu_data_i(sreg_execute_ack_c);
dci.exception_ack <= cpu_data_i(sreg_exception_ack_c);
end if;
end if;
end process write_access;
-- DM data buffer read access --
dci.rdata <= data_buf;
-- Read Access ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
read_access: process(clk_i)
begin
if rising_edge(clk_i) then
cpu_ack_o <= rden or wren;
cpu_data_o <= (others => '0');
if (rden = '1') then -- output gate
case maddr is -- module select
when "00" => -- code ROM
cpu_data_o <= code_rom_file(to_integer(unsigned(cpu_addr_i(6 downto 2))));
when "01" => -- program buffer
cpu_data_o <= cpu_progbuf(to_integer(unsigned(cpu_addr_i(3 downto 2))));
when "10" => -- data buffer
cpu_data_o <= data_buf;
when others => -- status/control register
cpu_data_o(sreg_resume_req_c) <= dci.resume_req;
cpu_data_o(sreg_execute_req_c) <= dci.execute_req;
end case;
end if;
end if;
end process read_access;
end neorv32_debug_dm_rtl;

View File

@ -0,0 +1,353 @@
-- #################################################################################################
-- # << NEORV32 - RISC-V Debug Transport Module (DTM) >> #
-- # ********************************************************************************************* #
-- # Provides a JTAG-compatible TAP to access the DMI register interface. #
-- # Compatible to the RISC-V debug specification. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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. #
-- # ********************************************************************************************* #
-- # https://github.com/stnolting/riscv-debug-dtm (c) Stephan Nolting #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
entity neorv32_debug_dtm is
generic (
IDCODE_VERSION : std_ulogic_vector(03 downto 0); -- version
IDCODE_PARTID : std_ulogic_vector(15 downto 0); -- part number
IDCODE_MANID : std_ulogic_vector(10 downto 0) -- manufacturer id
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock line
rstn_i : in std_ulogic; -- global reset line, low-active
-- jtag connection --
jtag_trst_i : in std_ulogic;
jtag_tck_i : in std_ulogic;
jtag_tdi_i : in std_ulogic;
jtag_tdo_o : out std_ulogic;
jtag_tms_i : in std_ulogic;
-- debug module interface (DMI) --
dmi_rstn_o : out std_ulogic;
dmi_req_valid_o : out std_ulogic;
dmi_req_ready_i : in std_ulogic; -- DMI is allowed to make new requests when set
dmi_req_addr_o : out std_ulogic_vector(06 downto 0);
dmi_req_op_o : out std_ulogic; -- 0=read, 1=write
dmi_req_data_o : out std_ulogic_vector(31 downto 0);
dmi_resp_valid_i : in std_ulogic; -- response valid when set
dmi_resp_ready_o : out std_ulogic; -- ready to receive respond
dmi_resp_data_i : in std_ulogic_vector(31 downto 0);
dmi_resp_err_i : in std_ulogic -- 0=ok, 1=error
);
end neorv32_debug_dtm;
architecture neorv32_debug_dtm_rtl of neorv32_debug_dtm is
-- DMI Configuration (fixed!) --
constant dmi_idle_c : std_ulogic_vector(02 downto 0) := "000"; -- no idle cycles required
constant dmi_version_c : std_ulogic_vector(03 downto 0) := "0001"; -- version (0.13)
constant dmi_abits_c : std_ulogic_vector(05 downto 0) := "000111"; -- number of DMI address bits (7)
-- tap JTAG signal synchronizer --
type tap_sync_t is record
-- internal --
trst_ff : std_ulogic_vector(2 downto 0);
tck_ff : std_ulogic_vector(2 downto 0);
tdi_ff : std_ulogic_vector(2 downto 0);
tms_ff : std_ulogic_vector(2 downto 0);
-- external --
trst : std_ulogic;
tck_rising : std_ulogic;
tck_falling : std_ulogic;
tdi : std_ulogic;
tdo : std_ulogic;
tms : std_ulogic;
end record;
signal tap_sync : tap_sync_t;
-- tap controller - fsm --
type tap_ctrl_state_t is (LOGIC_RESET, DR_SCAN, DR_CAPTURE, DR_SHIFT, DR_EXIT1, DR_PAUSE, DR_EXIT2, DR_UPDATE,
RUN_IDLE, IR_SCAN, IR_CAPTURE, IR_SHIFT, IR_EXIT1, IR_PAUSE, IR_EXIT2, IR_UPDATE);
type tap_ctrl_t is record
state : tap_ctrl_state_t;
state_prev : tap_ctrl_state_t;
end record;
signal tap_ctrl : tap_ctrl_t;
-- tap registers --
type tap_reg_t is record
ireg : std_ulogic_vector(04 downto 0);
bypass : std_ulogic;
idcode : std_ulogic_vector(31 downto 0);
dtmcs, dtmcs_nxt : std_ulogic_vector(31 downto 0);
dmi, dmi_nxt : std_ulogic_vector((7+32+2)-1 downto 0); -- 7-bit address + 32-bit data + 2-bit operation
end record;
signal tap_reg : tap_reg_t;
-- debug module interface --
type dmi_ctrl_state_t is (DMI_IDLE, DMI_READ_WAIT, DMI_READ, DMI_READ_BUSY,
DMI_WRITE_WAIT, DMI_WRITE, DMI_WRITE_BUSY);
type dmi_ctrl_t is record
state : dmi_ctrl_state_t;
--
dmihardreset : std_ulogic;
dmireset : std_ulogic;
--
err : std_ulogic; -- sticky error
rdata : std_ulogic_vector(31 downto 0);
wdata : std_ulogic_vector(31 downto 0);
addr : std_ulogic_vector(06 downto 0);
end record;
signal dmi_ctrl : dmi_ctrl_t;
begin
-- JTAG Signal Synchronizer ---------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
tap_synchronizer: process(rstn_i, clk_i)
begin
if rising_edge(clk_i) then
tap_sync.trst_ff <= tap_sync.trst_ff(1 downto 0) & jtag_trst_i;
tap_sync.tck_ff <= tap_sync.tck_ff( 1 downto 0) & jtag_tck_i;
tap_sync.tdi_ff <= tap_sync.tdi_ff( 1 downto 0) & jtag_tdi_i;
tap_sync.tms_ff <= tap_sync.tms_ff( 1 downto 0) & jtag_tms_i;
if (tap_sync.tck_falling = '1') then -- update output data TDO on falling edge of TCK
jtag_tdo_o <= tap_sync.tdo;
end if;
end if;
end process tap_synchronizer;
-- JTAG reset --
tap_sync.trst <= '0' when (tap_sync.trst_ff(2 downto 1) = "00") else '1';
-- JTAG clock edge --
tap_sync.tck_rising <= '1' when (tap_sync.tck_ff(2 downto 1) = "01") else '0';
tap_sync.tck_falling <= '1' when (tap_sync.tck_ff(2 downto 1) = "10") else '0';
-- JTAG test mode select --
tap_sync.tms <= tap_sync.tms_ff(2);
-- JTAG serial data input --
tap_sync.tdi <= tap_sync.tdi_ff(2);
-- Tap Control FSM ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
tap_control: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
tap_ctrl.state <= LOGIC_RESET;
tap_ctrl.state_prev <= LOGIC_RESET;
elsif rising_edge(clk_i) then
tap_ctrl.state_prev <= tap_ctrl.state;
if (tap_sync.trst = '0') then -- reset
tap_ctrl.state <= LOGIC_RESET;
elsif (tap_sync.tck_rising = '1') then -- clock pulse (evaluate TMS on the rising edge of TCK)
case tap_ctrl.state is -- JTAG state machine
when LOGIC_RESET => if (tap_sync.tms = '0') then tap_ctrl.state <= RUN_IDLE; else tap_ctrl.state <= LOGIC_RESET; end if;
when RUN_IDLE => if (tap_sync.tms = '0') then tap_ctrl.state <= RUN_IDLE; else tap_ctrl.state <= DR_SCAN; end if;
when DR_SCAN => if (tap_sync.tms = '0') then tap_ctrl.state <= DR_CAPTURE; else tap_ctrl.state <= IR_SCAN; end if;
when DR_CAPTURE => if (tap_sync.tms = '0') then tap_ctrl.state <= DR_SHIFT; else tap_ctrl.state <= DR_EXIT1; end if;
when DR_SHIFT => if (tap_sync.tms = '0') then tap_ctrl.state <= DR_SHIFT; else tap_ctrl.state <= DR_EXIT1; end if;
when DR_EXIT1 => if (tap_sync.tms = '0') then tap_ctrl.state <= DR_PAUSE; else tap_ctrl.state <= DR_UPDATE; end if;
when DR_PAUSE => if (tap_sync.tms = '0') then tap_ctrl.state <= DR_PAUSE; else tap_ctrl.state <= DR_EXIT2; end if;
when DR_EXIT2 => if (tap_sync.tms = '0') then tap_ctrl.state <= DR_SHIFT; else tap_ctrl.state <= DR_UPDATE; end if;
when DR_UPDATE => if (tap_sync.tms = '0') then tap_ctrl.state <= RUN_IDLE; else tap_ctrl.state <= DR_SCAN; end if;
when IR_SCAN => if (tap_sync.tms = '0') then tap_ctrl.state <= IR_CAPTURE; else tap_ctrl.state <= LOGIC_RESET; end if;
when IR_CAPTURE => if (tap_sync.tms = '0') then tap_ctrl.state <= IR_SHIFT; else tap_ctrl.state <= IR_EXIT1; end if;
when IR_SHIFT => if (tap_sync.tms = '0') then tap_ctrl.state <= IR_SHIFT; else tap_ctrl.state <= IR_EXIT1; end if;
when IR_EXIT1 => if (tap_sync.tms = '0') then tap_ctrl.state <= IR_PAUSE; else tap_ctrl.state <= IR_UPDATE; end if;
when IR_PAUSE => if (tap_sync.tms = '0') then tap_ctrl.state <= IR_PAUSE; else tap_ctrl.state <= IR_EXIT2; end if;
when IR_EXIT2 => if (tap_sync.tms = '0') then tap_ctrl.state <= IR_SHIFT; else tap_ctrl.state <= IR_UPDATE; end if;
when IR_UPDATE => if (tap_sync.tms = '0') then tap_ctrl.state <= RUN_IDLE; else tap_ctrl.state <= DR_SCAN; end if;
when others => tap_ctrl.state <= LOGIC_RESET;
end case;
end if;
end if;
end process tap_control;
-- Tap Register Access --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
reg_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- serial data input --
if (tap_sync.tck_rising = '1') then -- clock pulse (evaluate TDI on rising edge of TCK)
-- instruction register --
if (tap_ctrl.state = LOGIC_RESET) or (tap_ctrl.state = IR_CAPTURE) then -- reset or preload phase
tap_reg.ireg <= "00001"; -- IDCODE
elsif (tap_ctrl.state = IR_SHIFT) then -- access phase
tap_reg.ireg <= tap_sync.tdi & tap_reg.ireg(tap_reg.ireg'left downto 1);
end if;
-- data register --
if (tap_ctrl.state = DR_CAPTURE) then -- preload phase
case tap_reg.ireg is
when "00001" => tap_reg.idcode <= IDCODE_VERSION & IDCODE_PARTID & IDCODE_MANID & '1'; -- IDCODE (LSB has to be always set!)
when "10000" => tap_reg.dtmcs <= tap_reg.dtmcs_nxt;-- dtmcs
when "10001" => tap_reg.dmi <= tap_reg.dmi_nxt; -- dmi
when others => tap_reg.bypass <= '0'; -- BYPASS
end case;
elsif (tap_ctrl.state = DR_SHIFT) then -- access phase
case tap_reg.ireg is
when "00001" => tap_reg.idcode <= tap_sync.tdi & tap_reg.idcode(tap_reg.idcode'left downto 1); -- IDCODE
when "10000" => tap_reg.dtmcs <= tap_sync.tdi & tap_reg.dtmcs(tap_reg.dtmcs'left downto 1); -- dtmcs
when "10001" => tap_reg.dmi <= tap_sync.tdi & tap_reg.dmi(tap_reg.dmi'left downto 1); -- dmi
when others => tap_reg.bypass <= tap_sync.tdi; -- BYPASS
end case;
end if;
end if;
-- serial data output --
if (tap_ctrl.state = IR_SHIFT) then
tap_sync.tdo <= tap_reg.ireg(0);
else
case tap_reg.ireg is
when "00001" => tap_sync.tdo <= tap_reg.idcode(0); -- IDCODE
when "10000" => tap_sync.tdo <= tap_reg.dtmcs(0); -- dtmcs
when "10001" => tap_sync.tdo <= tap_reg.dmi(0); -- dmi
when others => tap_sync.tdo <= tap_reg.bypass; -- BYPASS
end case;
end if;
end if;
end process reg_access;
-- Debug Module Interface -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
dmi_controller: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
dmi_ctrl.state <= DMI_IDLE;
dmi_ctrl.dmihardreset <= '1';
dmi_ctrl.dmireset <= '1';
dmi_ctrl.err <= '0';
dmi_ctrl.rdata <= (others => '-');
dmi_ctrl.wdata <= (others => '-');
dmi_ctrl.addr <= (others => '-');
elsif rising_edge(clk_i) then
-- DMI status and control --
dmi_ctrl.dmihardreset <= '0'; -- default
dmi_ctrl.dmireset <= '0'; -- default
if (tap_ctrl.state = DR_UPDATE) and (tap_ctrl.state_prev /= DR_UPDATE) and (tap_reg.ireg = "10000") then
dmi_ctrl.dmireset <= tap_reg.dtmcs(16);
dmi_ctrl.dmihardreset <= tap_reg.dtmcs(17);
end if;
-- DMI interface arbiter --
if (dmi_ctrl.dmihardreset = '1') then -- DMI hard reset
dmi_ctrl.state <= DMI_IDLE;
dmi_ctrl.err <= '0';
else
case dmi_ctrl.state is
when DMI_IDLE => -- waiting for new request
if (tap_ctrl.state = DR_UPDATE) and (tap_ctrl.state_prev /= DR_UPDATE) and (tap_reg.ireg = "10001") then -- update <dmi>
if (tap_reg.dmi(1 downto 0) = "01") then -- read
dmi_ctrl.state <= DMI_READ_WAIT;
elsif (tap_reg.dmi(1 downto 0) = "10") then -- write
dmi_ctrl.state <= DMI_WRITE_WAIT;
end if;
dmi_ctrl.addr <= tap_reg.dmi(40 downto 34);
dmi_ctrl.wdata <= tap_reg.dmi(33 downto 02);
end if;
when DMI_READ_WAIT => -- wait for DMI to become ready
if (dmi_req_ready_i = '1') then
dmi_ctrl.state <= DMI_READ;
end if;
when DMI_READ => -- start read access
dmi_ctrl.state <= DMI_READ_BUSY;
when DMI_READ_BUSY => -- pending read access
if (dmi_resp_valid_i = '1') then
dmi_ctrl.rdata <= dmi_resp_data_i;
dmi_ctrl.err <= dmi_ctrl.err or dmi_resp_err_i; -- sticky error
dmi_ctrl.state <= DMI_IDLE;
end if;
when DMI_WRITE_WAIT => -- wait for DMI to become ready
if (dmi_req_ready_i = '1') then
dmi_ctrl.state <= DMI_WRITE;
end if;
when DMI_WRITE => -- start write access
dmi_ctrl.state <= DMI_WRITE_BUSY;
when DMI_WRITE_BUSY => -- pending write access
if (dmi_resp_valid_i = '1') then
dmi_ctrl.err <= dmi_ctrl.err or dmi_resp_err_i; -- sticky error
dmi_ctrl.state <= DMI_IDLE;
end if;
when others => -- undefined
dmi_ctrl.state <= DMI_IDLE;
end case;
-- clear sticky error flag --
if (dmi_ctrl.dmireset = '1') then
dmi_ctrl.err <= '0';
end if;
end if;
end if;
end process dmi_controller;
-- DTM Control and Status Register (dtmcs) --
tap_reg.dtmcs_nxt(31 downto 18) <= (others => '0'); -- unused
tap_reg.dtmcs_nxt(17) <= '0'; -- dmihardreset, always reads as zero
tap_reg.dtmcs_nxt(16) <= '0'; -- dmireset, always reads as zero
tap_reg.dtmcs_nxt(15) <= '0'; -- unused
tap_reg.dtmcs_nxt(14 downto 12) <= dmi_idle_c; -- minimum number of idle cycles
tap_reg.dtmcs_nxt(11 downto 10) <= tap_reg.dmi_nxt(1 downto 0); -- dmistat
tap_reg.dtmcs_nxt(09 downto 04) <= dmi_abits_c; -- number of DMI address bits
tap_reg.dtmcs_nxt(03 downto 00) <= dmi_version_c; -- version
-- DMI register read access --
tap_reg.dmi_nxt(40 downto 34) <= dmi_ctrl.addr; -- address
tap_reg.dmi_nxt(33 downto 02) <= dmi_ctrl.rdata; -- read data
tap_reg.dmi_nxt(01 downto 00) <= "11" when (dmi_ctrl.state /= DMI_IDLE) else (dmi_ctrl.err & '0'); -- status
-- direct DMI output --
dmi_rstn_o <= '0' when (dmi_ctrl.dmihardreset = '1') else '1';
dmi_req_valid_o <= '1' when (dmi_ctrl.state = DMI_READ) or (dmi_ctrl.state = DMI_WRITE) else '0';
dmi_req_op_o <= '1' when (dmi_ctrl.state = DMI_WRITE) or (dmi_ctrl.state = DMI_WRITE_BUSY) else '0';
dmi_resp_ready_o <= '1' when (dmi_ctrl.state = DMI_READ_BUSY) or (dmi_ctrl.state = DMI_WRITE_BUSY) else '0';
dmi_req_addr_o <= dmi_ctrl.addr;
dmi_req_data_o <= dmi_ctrl.wdata;
end neorv32_debug_dtm_rtl;

View File

@ -0,0 +1,54 @@
-- #################################################################################################
-- # << NEORV32 - Processor-internal data memory (DMEM) >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
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 (
clk_i : in std_ulogic; -- global clock line
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
ben_i : in std_ulogic_vector(03 downto 0); -- byte write enable
addr_i : in std_ulogic_vector(31 downto 0); -- address
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic -- transfer acknowledge
);
end neorv32_dmem;

View File

@ -0,0 +1,188 @@
-- #################################################################################################
-- # << NEORV32 - General Purpose FIFO Component >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_fifo is
generic (
FIFO_DEPTH : natural; -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH : natural; -- size of data elements in fifo
FIFO_RSYNC : boolean; -- false = async read; true = sync read
FIFO_SAFE : boolean -- true = allow read/write only if entry available
);
port (
-- control --
clk_i : in std_ulogic; -- clock, rising edge
rstn_i : in std_ulogic; -- async reset, low-active
clear_i : in std_ulogic; -- sync reset, high-active
level_o : out std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- fill level
half_o : out std_ulogic; -- FIFO is at least half full
-- write port --
wdata_i : in std_ulogic_vector(FIFO_WIDTH-1 downto 0); -- write data
we_i : in std_ulogic; -- write enable
free_o : out std_ulogic; -- at least one entry is free when set
-- read port --
re_i : in std_ulogic; -- read enable
rdata_o : out std_ulogic_vector(FIFO_WIDTH-1 downto 0); -- read data
avail_o : out std_ulogic -- data available when set
);
end neorv32_fifo;
architecture neorv32_fifo_rtl of neorv32_fifo is
-- FIFO --
type fifo_data_t is array (0 to FIFO_DEPTH-1) of std_ulogic_vector(FIFO_WIDTH-1 downto 0);
type fifo_t is record
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
w_pnt : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- write pointer
r_pnt : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- read pointer
level : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- fill count
data : fifo_data_t; -- fifo memory
datas : std_ulogic_vector(FIFO_WIDTH-1 downto 0);
match : std_ulogic;
empty : std_ulogic;
full : std_ulogic;
free : std_ulogic;
avail : std_ulogic;
end record;
signal fifo : fifo_t;
signal level_diff : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0);
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (FIFO_DEPTH = 0) report "NEORV32 CONFIG ERROR: FIFO depth has to be > 0." severity error;
assert not (is_power_of_two_f(FIFO_DEPTH) = false) report "NEORV32 CONFIG ERROR: FIFO depth has to be a power of two." severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
fifo.re <= re_i when (FIFO_SAFE = false) else (re_i and fifo.avail); -- read only if data available
fifo.we <= we_i when (FIFO_SAFE = false) else (we_i and fifo.free); -- write only if space left
-- FIFO Control ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
fifo_control: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
fifo.w_pnt <= (others => '0');
fifo.r_pnt <= (others => '0');
elsif rising_edge(clk_i) then
-- write port --
if (clear_i = '1') then
fifo.w_pnt <= (others => '0');
elsif (fifo.we = '1') then
fifo.w_pnt <= std_ulogic_vector(unsigned(fifo.w_pnt) + 1);
end if;
-- read port --
if (clear_i = '1') then
fifo.r_pnt <= (others => '0');
elsif (fifo.re = '1') then
fifo.r_pnt <= std_ulogic_vector(unsigned(fifo.r_pnt) + 1);
end if;
end if;
end process fifo_control;
-- status --
fifo.match <= '1' when (fifo.r_pnt(fifo.r_pnt'left-1 downto 0) = fifo.w_pnt(fifo.w_pnt'left-1 downto 0)) or (FIFO_DEPTH = 1) else '0';
fifo.full <= '1' when (fifo.r_pnt(fifo.r_pnt'left) /= fifo.w_pnt(fifo.w_pnt'left)) and (fifo.match = '1') else '0';
fifo.empty <= '1' when (fifo.r_pnt(fifo.r_pnt'left) = fifo.w_pnt(fifo.w_pnt'left)) and (fifo.match = '1') else '0';
fifo.free <= not fifo.full;
fifo.avail <= not fifo.empty;
level_diff <= std_ulogic_vector(unsigned(fifo.w_pnt) - unsigned(fifo.r_pnt));
fifo.level <= std_ulogic_vector(to_unsigned(FIFO_DEPTH, fifo.level'length)) when (fifo.full = '1') else level_diff;
-- status output --
level_o <= fifo.level;
free_o <= fifo.free;
avail_o <= fifo.avail;
fifo_half_level:
if (FIFO_DEPTH > 1) generate
half_o <= level_diff(level_diff'left-1) or fifo.full;
end generate;
fifo_half_level_simple:
if (FIFO_DEPTH = 1) generate
half_o <= fifo.full;
end generate;
-- FIFO Memory ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
fifo_memory_write: process(clk_i)
begin
if rising_edge(clk_i) then
if (fifo.we = '1') then
if (FIFO_DEPTH = 1) then
fifo.datas <= wdata_i;
else
fifo.data(to_integer(unsigned(fifo.w_pnt(fifo.w_pnt'left-1 downto 0)))) <= wdata_i;
end if;
end if;
end if;
end process fifo_memory_write;
-- asynchronous read --
fifo_read_async:
if (FIFO_RSYNC = false) generate
rdata_o <= fifo.datas when (FIFO_DEPTH = 1) else fifo.data(to_integer(unsigned(fifo.r_pnt(fifo.r_pnt'left-1 downto 0))));
end generate;
-- synchronous read --
fifo_read_sync:
if (FIFO_RSYNC = true) generate
fifo_memory_read: process(clk_i)
begin
if rising_edge(clk_i) then
if (FIFO_DEPTH = 1) then
rdata_o <= fifo.datas;
else
rdata_o <= fifo.data(to_integer(unsigned(fifo.r_pnt(fifo.r_pnt'left-1 downto 0))));
end if;
end if;
end process fifo_memory_read;
end generate;
end neorv32_fifo_rtl;

View File

@ -0,0 +1,126 @@
-- #################################################################################################
-- # << NEORV32 - General Purpose Parallel Input/Output Port (GPIO) >> #
-- # ********************************************************************************************* #
-- # 64-bit general purpose parallel input & output port unit. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_gpio is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- parallel io --
gpio_o : out std_ulogic_vector(63 downto 0);
gpio_i : in std_ulogic_vector(63 downto 0)
);
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_lo, din_hi : std_ulogic_vector(31 downto 0); -- r/-
signal dout_lo, dout_hi : std_ulogic_vector(31 downto 0); -- r/w
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- bus handshake --
ack_o <= wren or rden;
-- write access --
if (wren = '1') then
if (addr = gpio_out_lo_addr_c) then
dout_lo <= data_i;
end if;
if (addr = gpio_out_hi_addr_c) then
dout_hi <= data_i;
end if;
end if;
-- input buffer --
din_lo <= gpio_i(31 downto 00);
din_hi <= gpio_i(63 downto 32);
-- read access --
data_o <= (others => '0');
if (rden = '1') then
case addr(3 downto 2) is
when "00" => data_o <= din_lo;
when "01" => data_o <= din_hi;
when "10" => data_o <= dout_lo;
when others => data_o <= dout_hi;
end case;
end if;
end if;
end process rw_access;
-- output --
gpio_o <= dout_hi & dout_lo;
end neorv32_gpio_rtl;

View File

@ -0,0 +1,203 @@
-- #################################################################################################
-- # << NEORV32 - General Purpose Timer (GPTMR) >> #
-- # ********************************************************************************************* #
-- # 32-bit timer with configurable clock prescaler. The timer fires an interrupt whenever the #
-- # counter register value reaches the programmed threshold value. The timer can operate in #
-- # single-shot mode (count until it reaches THRESHOLD and stop) or in continuous mode (count #
-- # until it reaches THRESHOLD and auto-reset). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_gptmr is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- interrupt --
irq_o : out std_ulogic -- transmission done interrupt
);
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
constant ctrl_prsc1_c : natural := 2; -- r/w: clock prescaler select bit 1
constant ctrl_prsc2_c : natural := 3; -- r/w: clock prescaler select bit 2
constant ctrl_mode_c : natural := 4; -- r/w: mode (0=single-shot, 1=continuous)
--
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
-- clock generator --
signal gptmr_clk_en : std_ulogic;
-- timer core --
type timer_t is record
count : std_ulogic_vector(31 downto 0); -- counter register
thres : std_ulogic_vector(31 downto 0); -- threshold value
match : std_ulogic; -- count == thres
cnt_we : std_ulogic; -- write access to count
end record;
signal timer : timer_t;
-- interrupt detector --
signal irq_detect : std_ulogic_vector(1 downto 0);
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- bus access acknowledge --
ack_o <= rden or wren;
-- write access --
timer.cnt_we <= '0';
if (wren = '1') then
if (addr = gptmr_ctrl_addr_c) then -- control register
ctrl(ctrl_en_c) <= data_i(ctrl_en_c);
ctrl(ctrl_prsc0_c) <= data_i(ctrl_prsc0_c);
ctrl(ctrl_prsc1_c) <= data_i(ctrl_prsc1_c);
ctrl(ctrl_prsc2_c) <= data_i(ctrl_prsc2_c);
ctrl(ctrl_mode_c) <= data_i(ctrl_mode_c);
end if;
if (addr = gptmr_thres_addr_c) then -- threshold register
timer.thres <= data_i;
end if;
if (addr = gptmr_count_addr_c) then -- counter register
timer.cnt_we <= '1';
end if;
end if;
-- read access --
data_o <= (others => '0');
if (rden = '1') then
case addr(3 downto 2) is
when "00" => -- control register
data_o(ctrl_en_c) <= ctrl(ctrl_en_c);
data_o(ctrl_prsc0_c) <= ctrl(ctrl_prsc0_c);
data_o(ctrl_prsc1_c) <= ctrl(ctrl_prsc1_c);
data_o(ctrl_prsc2_c) <= ctrl(ctrl_prsc2_c);
data_o(ctrl_mode_c) <= ctrl(ctrl_mode_c);
when "01" => -- threshold register
data_o <= timer.thres;
when others => -- counter register
data_o <= timer.count;
end case;
end if;
end if;
end process rw_access;
-- clock generator enable --
clkgen_en_o <= ctrl(ctrl_en_c);
-- clock select --
gptmr_clk_en <= clkgen_i(to_integer(unsigned(ctrl(ctrl_prsc2_c downto ctrl_prsc0_c))));
-- Timer Core -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
timer_core: process(clk_i)
begin
if rising_edge(clk_i) then
if (timer.cnt_we = '1') then -- write access
timer.count <= data_i;
elsif (ctrl(ctrl_en_c) = '1') and (gptmr_clk_en = '1') then -- enabled and clock tick
if (timer.match = '1') then
if (ctrl(ctrl_mode_c) = '1') then -- reset counter if continuous mode
timer.count <= (others => '0');
end if;
else
timer.count <= std_ulogic_vector(unsigned(timer.count) + 1);
end if;
end if;
end if;
end process timer_core;
-- counter = threshold? --
timer.match <= '1' when (timer.count = timer.thres) else '0';
-- Interrupt Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
irq_generator: process(clk_i)
begin
if rising_edge(clk_i) then
if (ctrl(ctrl_en_c) = '0') then
irq_detect <= "00";
else
irq_detect <= irq_detect(0) & timer.match;
end if;
end if;
end process irq_generator;
-- IRQ request to CPU --
irq_o <= '1' when (irq_detect = "01") else '0';
end neorv32_gptmr_rtl;

View File

@ -0,0 +1,589 @@
-- #################################################################################################
-- # << NEORV32 - Processor-Internal Instruction Cache >> #
-- # ********************************************************************************************* #
-- # Direct mapped (ICACHE_NUM_SETS = 1) or 2-way set-associative (ICACHE_NUM_SETS = 2). #
-- # Least recently used replacement policy (if ICACHE_NUM_SETS > 1). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_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
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
clear_i : in std_ulogic; -- cache clear
-- host controller interface --
host_addr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
host_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
host_wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
host_ben_i : in std_ulogic_vector(03 downto 0); -- byte enable
host_we_i : in std_ulogic; -- write enable
host_re_i : in std_ulogic; -- read enable
host_ack_o : out std_ulogic; -- bus transfer acknowledge
host_err_o : out std_ulogic; -- bus transfer error
-- peripheral bus interface --
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
bus_we_o : out std_ulogic; -- write enable
bus_re_o : out std_ulogic; -- read enable
bus_ack_i : in std_ulogic; -- bus transfer acknowledge
bus_err_i : in std_ulogic -- bus transfer error
);
end neorv32_icache;
architecture neorv32_icache_rtl of neorv32_icache is
-- cache layout --
constant cache_offset_size_c : natural := index_size_f(ICACHE_BLOCK_SIZE/4); -- offset addresses full 32-bit words
constant cache_index_size_c : natural := index_size_f(ICACHE_NUM_BLOCKS);
constant cache_tag_size_c : natural := 32 - (cache_offset_size_c + cache_index_size_c + 2); -- 2 additonal bits for byte offset
-- cache memory --
component neorv32_icache_memory
generic (
ICACHE_NUM_BLOCKS : natural := 4; -- number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE : natural := 16; -- block size in bytes (min 4), has to be a power of 2
ICACHE_NUM_SETS : natural := 1 -- associativity; 0=direct-mapped, 1=2-way set-associative
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
invalidate_i : in std_ulogic; -- invalidate whole cache
-- host cache access (read-only) --
host_addr_i : in std_ulogic_vector(31 downto 0); -- access address
host_re_i : in std_ulogic; -- read enable
host_rdata_o : out std_ulogic_vector(31 downto 0); -- read data
-- access status (1 cycle delay to access) --
hit_o : out std_ulogic; -- hit access
-- ctrl cache access (write-only) --
ctrl_en_i : in std_ulogic; -- control interface enable
ctrl_addr_i : in std_ulogic_vector(31 downto 0); -- access address
ctrl_we_i : in std_ulogic; -- write enable (full-word)
ctrl_wdata_i : in std_ulogic_vector(31 downto 0); -- write data
ctrl_tag_we_i : in std_ulogic; -- write tag to selected block
ctrl_valid_i : in std_ulogic; -- make selected block valid
ctrl_invalid_i : in std_ulogic -- make selected block invalid
);
end component;
-- cache interface --
type cache_if_t is record
clear : std_ulogic; -- cache clear
--
host_addr : std_ulogic_vector(31 downto 0); -- cpu access address
host_rdata : std_ulogic_vector(31 downto 0); -- cpu read data
--
hit : std_ulogic; -- hit access
--
ctrl_en : std_ulogic; -- control access enable
ctrl_addr : std_ulogic_vector(31 downto 0); -- control access address
ctrl_we : std_ulogic; -- control write enable
ctrl_wdata : std_ulogic_vector(31 downto 0); -- control write data
ctrl_tag_we : std_ulogic; -- control tag write enabled
ctrl_valid_we : std_ulogic; -- control valid flag set
ctrl_invalid_we : std_ulogic; -- control valid flag clear
end record;
signal cache : cache_if_t;
-- control engine --
type ctrl_engine_state_t is (S_IDLE, S_CACHE_CLEAR, S_CACHE_CHECK, S_CACHE_MISS, S_BUS_DOWNLOAD_REQ, S_BUS_DOWNLOAD_GET,
S_CACHE_RESYNC_0, S_CACHE_RESYNC_1, S_BUS_ERROR);
type ctrl_t is record
state : ctrl_engine_state_t; -- current state
state_nxt : ctrl_engine_state_t; -- next state
addr_reg : std_ulogic_vector(31 downto 0); -- address register for block download
addr_reg_nxt : std_ulogic_vector(31 downto 0);
--
re_buf : std_ulogic; -- read request buffer
re_buf_nxt : std_ulogic;
--
clear_buf : std_ulogic; -- clear request buffer
clear_buf_nxt : std_ulogic;
end record;
signal ctrl : ctrl_t;
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 <ICACHE_NUM_BLOCKS> has to be a power of 2." severity error;
assert not (is_power_of_two_f(ICACHE_BLOCK_SIZE) = false) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache block size <ICACHE_BLOCK_SIZE> has to be a power of 2." severity error;
assert not ((is_power_of_two_f(ICACHE_NUM_SETS) = false)) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache associativity <ICACHE_NUM_SETS> has to be a power of 2." severity error;
assert not (ICACHE_NUM_BLOCKS < 1) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache number of blocks <ICACHE_NUM_BLOCKS> has to be >= 1." severity error;
assert not (ICACHE_BLOCK_SIZE < 4) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache block size <ICACHE_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 <ICACHE_NUM_SETS> has to be 1 (direct-mapped) or 2 (2-way set-associative)." severity error;
-- Control Engine FSM Sync ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- registers that REQUIRE a specific reset state --
ctrl_engine_fsm_sync_rst: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
ctrl.state <= S_CACHE_CLEAR;
ctrl.re_buf <= '0';
ctrl.clear_buf <= '0';
elsif rising_edge(clk_i) then
ctrl.state <= ctrl.state_nxt;
ctrl.re_buf <= ctrl.re_buf_nxt;
ctrl.clear_buf <= ctrl.clear_buf_nxt;
end if;
end process ctrl_engine_fsm_sync_rst;
-- registers that do not require a specific reset state --
ctrl_engine_fsm_sync: process(clk_i)
begin
if rising_edge(clk_i) then
ctrl.addr_reg <= ctrl.addr_reg_nxt;
end if;
end process ctrl_engine_fsm_sync;
-- Control Engine FSM Comb ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_engine_fsm_comb: process(ctrl, cache, clear_i, host_addr_i, host_re_i, bus_rdata_i, bus_ack_i, bus_err_i)
begin
-- control defaults --
ctrl.state_nxt <= ctrl.state;
ctrl.addr_reg_nxt <= ctrl.addr_reg;
ctrl.re_buf_nxt <= ctrl.re_buf or host_re_i;
ctrl.clear_buf_nxt <= ctrl.clear_buf or clear_i; -- buffer clear request from CPU
-- cache defaults --
cache.clear <= '0';
cache.host_addr <= host_addr_i;
cache.ctrl_en <= '0';
cache.ctrl_addr <= ctrl.addr_reg;
cache.ctrl_we <= '0';
cache.ctrl_wdata <= bus_rdata_i;
cache.ctrl_tag_we <= '0';
cache.ctrl_valid_we <= '0';
cache.ctrl_invalid_we <= '0';
-- host interface defaults --
host_ack_o <= '0';
host_err_o <= '0';
host_rdata_o <= cache.host_rdata;
-- peripheral bus interface defaults --
bus_addr_o <= ctrl.addr_reg;
bus_wdata_o <= (others => '0'); -- cache is read-only
bus_ben_o <= (others => '0'); -- cache is read-only
bus_we_o <= '0'; -- cache is read-only
bus_re_o <= '0';
-- fsm --
case ctrl.state is
when S_IDLE => -- wait for host access request or cache control operation
-- ------------------------------------------------------------
if (ctrl.clear_buf = '1') then -- cache control operation?
ctrl.state_nxt <= S_CACHE_CLEAR;
elsif (host_re_i = '1') or (ctrl.re_buf = '1') then -- cache access
ctrl.re_buf_nxt <= '0';
ctrl.state_nxt <= S_CACHE_CHECK;
end if;
when S_CACHE_CLEAR => -- invalidate all cache entries
-- ------------------------------------------------------------
ctrl.clear_buf_nxt <= '0';
cache.clear <= '1';
ctrl.state_nxt <= S_IDLE;
when S_CACHE_CHECK => -- finalize host access if cache hit
-- ------------------------------------------------------------
if (cache.hit = '1') then -- cache HIT
host_ack_o <= '1';
ctrl.state_nxt <= S_IDLE;
else -- cache MISS
ctrl.state_nxt <= S_CACHE_MISS;
end if;
when S_CACHE_MISS => --
-- ------------------------------------------------------------
-- compute block base address --
ctrl.addr_reg_nxt <= host_addr_i;
ctrl.addr_reg_nxt((2+cache_offset_size_c)-1 downto 2) <= (others => '0'); -- block-aligned
ctrl.addr_reg_nxt(1 downto 0) <= "00"; -- word-aligned
--
ctrl.state_nxt <= S_BUS_DOWNLOAD_REQ;
when S_BUS_DOWNLOAD_REQ => -- download new cache block: request new word
-- ------------------------------------------------------------
cache.ctrl_en <= '1'; -- we are in cache control mode
bus_re_o <= '1'; -- request new read transfer
ctrl.state_nxt <= S_BUS_DOWNLOAD_GET;
when S_BUS_DOWNLOAD_GET => -- download new cache block: wait for bus response
-- ------------------------------------------------------------
cache.ctrl_en <= '1'; -- we are in cache control mode
--
if (bus_err_i = '1') then -- bus error
ctrl.state_nxt <= S_BUS_ERROR;
elsif (bus_ack_i = '1') then -- ACK = write to cache and get next word
cache.ctrl_we <= '1'; -- write to cache
if (and_reduce_f(ctrl.addr_reg((2+cache_offset_size_c)-1 downto 2)) = '1') then -- block complete?
cache.ctrl_tag_we <= '1'; -- current block is valid now
cache.ctrl_valid_we <= '1'; -- write tag of current address
ctrl.state_nxt <= S_CACHE_RESYNC_0;
else -- get next word
ctrl.addr_reg_nxt <= std_ulogic_vector(unsigned(ctrl.addr_reg) + 4);
ctrl.state_nxt <= S_BUS_DOWNLOAD_REQ;
end if;
end if;
when S_CACHE_RESYNC_0 => -- re-sync host/cache access: cache read-latency
-- ------------------------------------------------------------
ctrl.state_nxt <= S_CACHE_RESYNC_1;
when S_CACHE_RESYNC_1 => -- re-sync host/cache access: finalize CPU request
-- ------------------------------------------------------------
host_ack_o <= '1';
ctrl.state_nxt <= S_IDLE;
when S_BUS_ERROR => -- bus error during download
-- ------------------------------------------------------------
host_err_o <= '1';
ctrl.state_nxt <= S_IDLE;
when others => -- undefined
-- ------------------------------------------------------------
ctrl.state_nxt <= S_IDLE;
end case;
end process ctrl_engine_fsm_comb;
-- Cache Memory ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_icache_memory_inst: neorv32_icache_memory
generic map (
ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, -- number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, -- block size in bytes (min 4), has to be a power of 2
ICACHE_NUM_SETS => ICACHE_NUM_SETS -- associativity; 0=direct-mapped, 1=2-way set-associative
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
invalidate_i => cache.clear, -- invalidate whole cache
-- host cache access (read-only) --
host_addr_i => cache.host_addr, -- access address
host_re_i => host_re_i, -- read enable
host_rdata_o => cache.host_rdata, -- read data
-- access status (1 cycle delay to access) --
hit_o => cache.hit, -- hit access
-- ctrl cache access (write-only) --
ctrl_en_i => cache.ctrl_en, -- control interface enable
ctrl_addr_i => cache.ctrl_addr, -- access address
ctrl_we_i => cache.ctrl_we, -- write enable (full-word)
ctrl_wdata_i => cache.ctrl_wdata, -- write data
ctrl_tag_we_i => cache.ctrl_tag_we, -- write tag to selected block
ctrl_valid_i => cache.ctrl_valid_we, -- make selected block valid
ctrl_invalid_i => cache.ctrl_invalid_we -- make selected block invalid
);
end neorv32_icache_rtl;
-- ###########################################################################################################################################
-- ###########################################################################################################################################
-- #################################################################################################
-- # << NEORV32 - Cache Memory >> #
-- # ********************************************************************************************* #
-- # Direct mapped (ICACHE_NUM_SETS = 1) or 2-way set-associative (ICACHE_NUM_SETS = 2). #
-- # Least recently used replacement policy (if ICACHE_NUM_SETS > 1). #
-- # Read-only for host, write-only for control. All output signals have one cycle latency. #
-- # #
-- # Cache sets are mapped to individual memory components - no multi-dimensional memory arrays #
-- # are used as some synthesis tools have problems to map these to actual BRAM primitives. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2020, 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_icache_memory is
generic (
ICACHE_NUM_BLOCKS : natural := 4; -- number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE : natural := 16; -- block size in bytes (min 4), has to be a power of 2
ICACHE_NUM_SETS : natural := 1 -- associativity; 1=direct-mapped, 2=2-way set-associative
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
invalidate_i : in std_ulogic; -- invalidate whole cache
-- host cache access (read-only) --
host_addr_i : in std_ulogic_vector(31 downto 0); -- access address
host_re_i : in std_ulogic; -- read enable
host_rdata_o : out std_ulogic_vector(31 downto 0); -- read data
-- access status (1 cycle delay to access) --
hit_o : out std_ulogic; -- hit access
-- ctrl cache access (write-only) --
ctrl_en_i : in std_ulogic; -- control interface enable
ctrl_addr_i : in std_ulogic_vector(31 downto 0); -- access address
ctrl_we_i : in std_ulogic; -- write enable (full-word)
ctrl_wdata_i : in std_ulogic_vector(31 downto 0); -- write data
ctrl_tag_we_i : in std_ulogic; -- write tag to selected block
ctrl_valid_i : in std_ulogic; -- make selected block valid
ctrl_invalid_i : in std_ulogic -- make selected block invalid
);
end neorv32_icache_memory;
architecture neorv32_icache_memory_rtl of neorv32_icache_memory is
-- cache layout --
constant cache_offset_size_c : natural := index_size_f(ICACHE_BLOCK_SIZE/4); -- offset addresses full 32-bit words
constant cache_index_size_c : natural := index_size_f(ICACHE_NUM_BLOCKS);
constant cache_tag_size_c : natural := 32 - (cache_offset_size_c + cache_index_size_c + 2); -- 2 additonal bits for byte offset
constant cache_entries_c : natural := ICACHE_NUM_BLOCKS * (ICACHE_BLOCK_SIZE/4); -- number of 32-bit entries (per set)
-- status flag memory --
signal valid_flag_s0 : std_ulogic_vector(ICACHE_NUM_BLOCKS-1 downto 0);
signal valid_flag_s1 : std_ulogic_vector(ICACHE_NUM_BLOCKS-1 downto 0);
signal valid : std_ulogic_vector(1 downto 0); -- valid flag read data
-- tag memory --
type tag_mem_t is array (0 to ICACHE_NUM_BLOCKS-1) of std_ulogic_vector(cache_tag_size_c-1 downto 0);
signal tag_mem_s0 : tag_mem_t;
signal tag_mem_s1 : tag_mem_t;
type tag_rd_t is array (0 to 1) of std_ulogic_vector(cache_tag_size_c-1 downto 0);
signal tag : tag_rd_t; -- tag read data
-- access status --
signal hit : std_ulogic_vector(1 downto 0);
-- access address decomposition --
type acc_addr_t is record
tag : std_ulogic_vector(cache_tag_size_c-1 downto 0);
index : std_ulogic_vector(cache_index_size_c-1 downto 0);
offset : std_ulogic_vector(cache_offset_size_c-1 downto 0);
end record;
signal host_acc_addr, ctrl_acc_addr : acc_addr_t;
-- cache data memory --
type cache_mem_t is array (0 to cache_entries_c-1) of std_ulogic_vector(31 downto 0);
signal cache_data_memory_s0 : cache_mem_t; -- set 0
signal cache_data_memory_s1 : cache_mem_t; -- set 1
-- cache data memory access --
type cache_rdata_t is array (0 to 1) of std_ulogic_vector(31 downto 0);
signal cache_rdata : cache_rdata_t;
signal cache_index : std_ulogic_vector(cache_index_size_c-1 downto 0);
signal cache_offset : std_ulogic_vector(cache_offset_size_c-1 downto 0);
signal cache_addr : std_ulogic_vector((cache_index_size_c+cache_offset_size_c)-1 downto 0); -- index & offset
signal cache_we : std_ulogic; -- write enable (full-word)
signal set_select : std_ulogic;
-- access history --
type history_t is record
re_ff : std_ulogic;
last_used_set : std_ulogic_vector(ICACHE_NUM_BLOCKS-1 downto 0);
to_be_replaced : std_ulogic;
end record;
signal history : history_t;
begin
-- Access Address Decomposition -----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
host_acc_addr.tag <= host_addr_i(31 downto 31-(cache_tag_size_c-1));
host_acc_addr.index <= host_addr_i(31-cache_tag_size_c downto 2+cache_offset_size_c);
host_acc_addr.offset <= host_addr_i(2+(cache_offset_size_c-1) downto 2); -- discard byte offset
ctrl_acc_addr.tag <= ctrl_addr_i(31 downto 31-(cache_tag_size_c-1));
ctrl_acc_addr.index <= ctrl_addr_i(31-cache_tag_size_c downto 2+cache_offset_size_c);
ctrl_acc_addr.offset <= ctrl_addr_i(2+(cache_offset_size_c-1) downto 2); -- discard byte offset
-- Cache Access History -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
access_history: process(clk_i)
begin
if rising_edge(clk_i) then
history.re_ff <= host_re_i;
if (invalidate_i = '1') then -- invalidate whole cache
history.last_used_set <= (others => '1');
elsif (history.re_ff = '1') and (or_reduce_f(hit) = '1') and (ctrl_en_i = '0') then -- store last accessed set that caused a hit
history.last_used_set(to_integer(unsigned(cache_index))) <= not hit(0);
end if;
history.to_be_replaced <= history.last_used_set(to_integer(unsigned(cache_index)));
end if;
end process access_history;
-- which set is going to be replaced? -> opposite of last used set = least recently used set --
set_select <= '0' when (ICACHE_NUM_SETS = 1) else (not history.to_be_replaced);
-- Status flag memory ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
status_memory: process(clk_i)
begin
if rising_edge(clk_i) then
-- write access --
if (invalidate_i = '1') then -- invalidate whole cache
valid_flag_s0 <= (others => '0');
valid_flag_s1 <= (others => '0');
elsif (ctrl_en_i = '1') then
if (ctrl_invalid_i = '1') then -- make current block invalid
if (set_select = '0') then
valid_flag_s0(to_integer(unsigned(cache_index))) <= '0';
else
valid_flag_s1(to_integer(unsigned(cache_index))) <= '0';
end if;
elsif (ctrl_valid_i = '1') then -- make current block valid
if (set_select = '0') then
valid_flag_s0(to_integer(unsigned(cache_index))) <= '1';
else
valid_flag_s1(to_integer(unsigned(cache_index))) <= '1';
end if;
end if;
end if;
-- read access (sync) --
valid(0) <= valid_flag_s0(to_integer(unsigned(cache_index)));
valid(1) <= valid_flag_s1(to_integer(unsigned(cache_index)));
end if;
end process status_memory;
-- Tag memory -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
tag_memory: process(clk_i)
begin
if rising_edge(clk_i) then
if (ctrl_en_i = '1') and (ctrl_tag_we_i = '1') then -- write access
if (set_select = '0') then
tag_mem_s0(to_integer(unsigned(cache_index))) <= ctrl_acc_addr.tag;
else
tag_mem_s1(to_integer(unsigned(cache_index))) <= ctrl_acc_addr.tag;
end if;
end if;
tag(0) <= tag_mem_s0(to_integer(unsigned(cache_index)));
tag(1) <= tag_mem_s1(to_integer(unsigned(cache_index)));
end if;
end process tag_memory;
-- comparator --
comparator: process(host_acc_addr, tag, valid)
begin
hit <= (others => '0');
for i in 0 to ICACHE_NUM_SETS-1 loop
if (host_acc_addr.tag = tag(i)) and (valid(i) = '1') then
hit(i) <= '1';
end if;
end loop; -- i
end process comparator;
-- global hit --
hit_o <= or_reduce_f(hit);
-- Cache Data Memory ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
cache_mem_access: process(clk_i)
begin
if rising_edge(clk_i) then
if (cache_we = '1') then -- write access from control (full-word)
if (set_select = '0') or (ICACHE_NUM_SETS = 1) then
cache_data_memory_s0(to_integer(unsigned(cache_addr))) <= ctrl_wdata_i;
else
cache_data_memory_s1(to_integer(unsigned(cache_addr))) <= ctrl_wdata_i;
end if;
end if;
-- read access from host (full-word) --
cache_rdata(0) <= cache_data_memory_s0(to_integer(unsigned(cache_addr)));
cache_rdata(1) <= cache_data_memory_s1(to_integer(unsigned(cache_addr)));
end if;
end process cache_mem_access;
-- data output --
host_rdata_o <= cache_rdata(0) when (hit(0) = '1') or (ICACHE_NUM_SETS = 1) else cache_rdata(1);
-- cache block ram access address --
cache_addr <= cache_index & cache_offset;
-- cache access select --
cache_index <= host_acc_addr.index when (ctrl_en_i = '0') else ctrl_acc_addr.index;
cache_offset <= host_acc_addr.offset when (ctrl_en_i = '0') else ctrl_acc_addr.offset;
cache_we <= '0' when (ctrl_en_i = '0') else ctrl_we_i;
end neorv32_icache_memory_rtl;

View File

@ -0,0 +1,58 @@
-- #################################################################################################
-- # << NEORV32 - Processor-internal instruction memory (IMEM) >> #
-- # ********************************************************************************************* #
-- # This memory optionally includes the in-place executable image of the application. See the #
-- # processor's documentary to get more information. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
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?
);
port (
clk_i : in std_ulogic; -- global clock line
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
ben_i : in std_ulogic_vector(03 downto 0); -- byte write enable
addr_i : in std_ulogic_vector(31 downto 0); -- address
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic -- transfer acknowledge
);
end neorv32_imem;

View File

@ -0,0 +1,181 @@
-- #################################################################################################
-- # << NEORV32 - Machine System Timer (MTIME) >> #
-- # ********************************************************************************************* #
-- # Compatible to RISC-V spec's 64-bit MACHINE system timer including "mtime[h]" & "mtimecmp[h]". #
-- # Note: The 64-bit counter and compare systems are de-coupled into two 32-bit systems. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_mtime is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- time output for CPU --
time_o : out std_ulogic_vector(63 downto 0); -- current system time
-- interrupt --
irq_o : out std_ulogic -- interrupt request
);
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;
-- accessible regs --
signal mtimecmp_lo : std_ulogic_vector(31 downto 0);
signal mtimecmp_hi : std_ulogic_vector(31 downto 0);
signal mtime_lo : std_ulogic_vector(31 downto 0);
signal mtime_lo_nxt : std_ulogic_vector(32 downto 0);
signal mtime_lo_ovfl : std_ulogic_vector(00 downto 0);
signal mtime_hi : std_ulogic_vector(31 downto 0);
-- comparators --
signal cmp_lo_ge : std_ulogic;
signal cmp_lo_ge_ff : std_ulogic;
signal cmp_hi_eq : std_ulogic;
signal cmp_hi_gt : std_ulogic;
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Write Access ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
wr_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- mtimecmp --
if (wren = '1') then
if (addr = mtime_cmp_lo_addr_c) then
mtimecmp_lo <= data_i;
end if;
if (addr = mtime_cmp_hi_addr_c) then
mtimecmp_hi <= data_i;
end if;
end if;
-- mtime access buffer --
-- wdata_buf <= data_i; -- not required, CPU wdata (=data_i) is stable until transfer is acknowledged
mtime_lo_we <= wren and bool_to_ulogic_f(boolean(addr = mtime_time_lo_addr_c));
mtime_hi_we <= wren and bool_to_ulogic_f(boolean(addr = mtime_time_hi_addr_c));
-- mtime low --
if (mtime_lo_we = '1') then -- write access
mtime_lo <= data_i;
else -- auto increment
mtime_lo <= mtime_lo_nxt(31 downto 0);
end if;
mtime_lo_ovfl(0) <= mtime_lo_nxt(32); -- overflow (carry)
-- mtime high --
if (mtime_hi_we = '1') then -- write access
mtime_hi <= data_i;
else -- auto increment (if mtime.low overflows)
mtime_hi <= std_ulogic_vector(unsigned(mtime_hi) + unsigned(mtime_lo_ovfl));
end if;
end if;
end process wr_access;
-- mtime.time_LO increment --
mtime_lo_nxt <= std_ulogic_vector(unsigned('0' & mtime_lo) + 1);
-- Read Access ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rd_access: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= rden or wren;
data_o <= (others => '0'); -- default
if (rden = '1') then
case addr(3 downto 2) is
when "00" => data_o <= mtime_lo; -- mtime LOW
when "01" => data_o <= mtime_hi; -- mtime HIGH
when "10" => data_o <= mtimecmp_lo; -- mtimecmp LOW
when others => data_o <= mtimecmp_hi; -- mtimecmp HIGH
end case;
end if;
end if;
end process rd_access;
-- system time output for cpu --
time_o <= mtime_hi & mtime_lo; -- NOTE: low and high words are not synchronized here!
-- Comparator -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
cmp_sync: process(clk_i)
begin
if rising_edge(clk_i) then
cmp_lo_ge_ff <= cmp_lo_ge; -- there is one cycle delay between low (earlier) and high (later) word
irq_o <= cmp_hi_gt or (cmp_hi_eq and cmp_lo_ge_ff);
end if;
end process cmp_sync;
-- sub-word comparators --
cmp_lo_ge <= '1' when (unsigned(mtime_lo) >= unsigned(mtimecmp_lo)) else '0'; -- low-word: greater than or equal
cmp_hi_eq <= '1' when (unsigned(mtime_hi) = unsigned(mtimecmp_hi)) else '0'; -- high-word: equal
cmp_hi_gt <= '1' when (unsigned(mtime_hi) > unsigned(mtimecmp_hi)) else '0'; -- high-word: greater than
end neorv32_mtime_rtl;

View File

@ -0,0 +1,420 @@
-- #################################################################################################
-- # << NEORV32 - Smart LED (WS2811/WS2812) Interface (NEOLED) >> #
-- # ********************************************************************************************* #
-- # Hardware interface for direct control of "smart LEDs" using an asynchronous serial data #
-- # line. Compatible with the WS2811 and WS2812 LEDs. #
-- # #
-- # NeoPixel-compatible, RGB (24-bit) and RGBW (32-bit) modes supported (in "parallel") #
-- # (TM) "NeoPixel" is a trademark of Adafruit Industries. #
-- # #
-- # The interface uses a programmable carrier frequency (800 KHz for the WS2812 LEDs) #
-- # configurable via the control register's clock prescaler bits (ctrl_clksel*_c) and the period #
-- # length configuration bits (ctrl_t_tot_*_c). "high-times" for sending a ZERO or a ONE bit are #
-- # configured using the ctrl_t_0h_*_c and ctrl_t_1h_*_c bits, respectively. 32-bit transfers #
-- # (for RGBW modules) and 24-bit transfers (for RGB modules) are supported via ctrl_mode__c. #
-- # #
-- # The device features a TX buffer (FIFO) with <FIFO_DEPTH> entries with configurable interrupt. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_neoled is
generic (
FIFO_DEPTH : natural -- TX FIFO depth (1..32k, power of two)
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- interrupt --
irq_o : out std_ulogic; -- interrupt request
-- NEOLED output --
neoled_o : out std_ulogic -- serial async data line
);
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
constant ctrl_strobe_c : natural := 2; -- r/w: 0 = send normal data, 1 = send LED strobe command (RESET) on data write
--
constant ctrl_clksel0_c : natural := 3; -- r/w: prescaler select bit 0
constant ctrl_clksel1_c : natural := 4; -- r/w: prescaler select bit 1
constant ctrl_clksel2_c : natural := 5; -- r/w: prescaler select bit 2
--
constant ctrl_bufs_0_c : natural := 6; -- r/-: log2(FIFO_DEPTH) bit 0
constant ctrl_bufs_1_c : natural := 7; -- r/-: log2(FIFO_DEPTH) bit 1
constant ctrl_bufs_2_c : natural := 8; -- r/-: log2(FIFO_DEPTH) bit 2
constant ctrl_bufs_3_c : natural := 9; -- r/-: log2(FIFO_DEPTH) bit 3
--
constant ctrl_t_tot_0_c : natural := 10; -- r/w: pulse-clock ticks per total period bit 0
constant ctrl_t_tot_1_c : natural := 11; -- r/w: pulse-clock ticks per total period bit 1
constant ctrl_t_tot_2_c : natural := 12; -- r/w: pulse-clock ticks per total period bit 2
constant ctrl_t_tot_3_c : natural := 13; -- r/w: pulse-clock ticks per total period bit 3
constant ctrl_t_tot_4_c : natural := 14; -- r/w: pulse-clock ticks per total period bit 4
--
constant ctrl_t_0h_0_c : natural := 15; -- r/w: pulse-clock ticks per ZERO high-time bit 0
constant ctrl_t_0h_1_c : natural := 16; -- r/w: pulse-clock ticks per ZERO high-time bit 1
constant ctrl_t_0h_2_c : natural := 17; -- r/w: pulse-clock ticks per ZERO high-time bit 2
constant ctrl_t_0h_3_c : natural := 18; -- r/w: pulse-clock ticks per ZERO high-time bit 3
constant ctrl_t_0h_4_c : natural := 19; -- r/w: pulse-clock ticks per ZERO high-time bit 4
--
constant ctrl_t_1h_0_c : natural := 20; -- r/w: pulse-clock ticks per ONE high-time bit 0
constant ctrl_t_1h_1_c : natural := 21; -- r/w: pulse-clock ticks per ONE high-time bit 1
constant ctrl_t_1h_2_c : natural := 22; -- r/w: pulse-clock ticks per ONE high-time bit 2
constant ctrl_t_1h_3_c : natural := 23; -- r/w: pulse-clock ticks per ONE high-time bit 3
constant ctrl_t_1h_4_c : natural := 24; -- r/w: pulse-clock ticks per ONE high-time bit 4
--
constant ctrl_irq_conf_c : natural := 27; -- r/w: interrupt config: 1=IRQ when buffer is empty, 0=IRQ when buffer is half-empty
constant ctrl_tx_empty_c : natural := 28; -- r/-: TX FIFO is empty
constant ctrl_tx_half_c : natural := 29; -- r/-: TX FIFO is at least half-full
constant ctrl_tx_full_c : natural := 30; -- r/-: TX FIFO is full
constant ctrl_tx_busy_c : natural := 31; -- r/-: serial TX engine busy when set
-- control register --
type ctrl_t is record
enable : std_ulogic;
mode : std_ulogic;
strobe : std_ulogic;
clk_prsc : std_ulogic_vector(2 downto 0);
irq_conf : std_ulogic;
-- pulse config --
t_total : std_ulogic_vector(4 downto 0);
t0_high : std_ulogic_vector(4 downto 0);
t1_high : std_ulogic_vector(4 downto 0);
end record;
signal ctrl : ctrl_t;
-- transmission buffer --
type tx_buffer_t is record
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
clear : std_ulogic; -- sync reset, high-active
wdata : std_ulogic_vector(31+2 downto 0); -- write data (excluding mode)
rdata : std_ulogic_vector(31+2 downto 0); -- read data (including mode)
avail : std_ulogic; -- data available?
free : std_ulogic; -- free entry available?
half : std_ulogic; -- half full
end record;
signal tx_buffer : tx_buffer_t;
-- interrupt generator --
type irq_t is record
set : std_ulogic;
buf : std_ulogic_vector(1 downto 0);
end record;
signal irq : irq_t;
-- serial transmission engine --
type serial_state_t is (S_IDLE, S_INIT, S_GETBIT, S_PULSE, S_STROBE);
type serial_t is record
-- state control --
state : serial_state_t;
mode : std_ulogic;
done : std_ulogic;
busy : std_ulogic;
bit_cnt : std_ulogic_vector(5 downto 0);
-- shift register --
sreg : std_ulogic_vector(31 downto 0);
next_bit : std_ulogic; -- next bit to send
-- pulse generator --
pulse_clk : std_ulogic; -- pulse cycle "clock"
pulse_cnt : std_ulogic_vector(4 downto 0);
t_high : std_ulogic_vector(4 downto 0);
strobe_cnt : std_ulogic_vector(6 downto 0);
tx_out : std_ulogic;
end record;
signal serial : serial_t;
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not ((is_power_of_two_f(FIFO_DEPTH) = false) or (FIFO_DEPTH < 1) or (FIFO_DEPTH > 32768)) report
"NEORV32 PROCESSOR CONFIG ERROR! Invalid <NEOLED.FIFO_DEPTH> buffer size configuration (1..32k)!" severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- access acknowledge --
ack_o <= wren or rden;
-- write access: control register --
if (wren = '1') and (addr = neoled_ctrl_addr_c) then
ctrl.enable <= data_i(ctrl_en_c);
ctrl.mode <= data_i(ctrl_mode_c);
ctrl.strobe <= data_i(ctrl_strobe_c);
ctrl.clk_prsc <= data_i(ctrl_clksel2_c downto ctrl_clksel0_c);
ctrl.irq_conf <= data_i(ctrl_irq_conf_c);
ctrl.t_total <= data_i(ctrl_t_tot_4_c downto ctrl_t_tot_0_c);
ctrl.t0_high <= data_i(ctrl_t_0h_4_c downto ctrl_t_0h_0_c);
ctrl.t1_high <= data_i(ctrl_t_1h_4_c downto ctrl_t_1h_0_c);
end if;
-- read access: control register --
data_o <= (others => '0');
if (rden = '1') then -- and (addr = neoled_ctrl_addr_c) then
data_o(ctrl_en_c) <= ctrl.enable;
data_o(ctrl_mode_c) <= ctrl.mode;
data_o(ctrl_strobe_c) <= ctrl.strobe;
data_o(ctrl_clksel2_c downto ctrl_clksel0_c) <= ctrl.clk_prsc;
data_o(ctrl_irq_conf_c) <= ctrl.irq_conf or bool_to_ulogic_f(boolean(FIFO_DEPTH = 1)); -- tie to one if FIFO_DEPTH is 1
data_o(ctrl_bufs_3_c downto ctrl_bufs_0_c) <= std_ulogic_vector(to_unsigned(index_size_f(FIFO_DEPTH), 4));
data_o(ctrl_t_tot_4_c downto ctrl_t_tot_0_c) <= ctrl.t_total;
data_o(ctrl_t_0h_4_c downto ctrl_t_0h_0_c) <= ctrl.t0_high;
data_o(ctrl_t_1h_4_c downto ctrl_t_1h_0_c) <= ctrl.t1_high;
--
data_o(ctrl_tx_empty_c) <= not tx_buffer.avail;
data_o(ctrl_tx_half_c) <= tx_buffer.half;
data_o(ctrl_tx_full_c) <= not tx_buffer.free;
data_o(ctrl_tx_busy_c) <= serial.busy;
end if;
end if;
end process rw_access;
-- enable external clock generator --
clkgen_en_o <= ctrl.enable;
-- FIFO write access --
tx_buffer.we <= '1' when (wren = '1') and (addr = neoled_data_addr_c) else '0';
tx_buffer.wdata <= ctrl.strobe & ctrl.mode & data_i;
tx_buffer.clear <= not ctrl.enable;
-- IRQ Generator --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
irq_select: process(ctrl, tx_buffer, serial.done)
begin
if (FIFO_DEPTH = 1) or (ctrl.irq_conf = '1') then
irq.set <= tx_buffer.free and serial.done; -- fire IRQ if FIFO is empty
else
irq.set <= not tx_buffer.half; -- fire IRQ if FIFO is less than half-full
end if;
end process irq_select;
-- Interrupt Edge Detector --
irq_detect: process(clk_i)
begin
if rising_edge(clk_i) then
if (ctrl.enable = '0') then
irq.buf <= "00";
else
irq.buf <= irq.buf(0) & irq.set;
end if;
end if;
end process irq_detect;
-- IRQ request to CPU --
irq_o <= '1' when (irq.buf = "01") else '0';
-- TX Buffer (FIFO) -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
tx_data_fifo: neorv32_fifo
generic map (
FIFO_DEPTH => FIFO_DEPTH, -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH => 32+2, -- size of data elements in fifo
FIFO_RSYNC => true, -- sync read
FIFO_SAFE => true -- safe access
)
port map (
-- control --
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => tx_buffer.clear, -- sync reset, high-active
level_o => open, -- fill level
half_o => tx_buffer.half, -- FIFO is at least half full
-- write port --
wdata_i => tx_buffer.wdata, -- write data
we_i => tx_buffer.we, -- write enable
free_o => tx_buffer.free, -- at least one entry is free when set
-- read port --
re_i => tx_buffer.re, -- read enable
rdata_o => tx_buffer.rdata, -- read data
avail_o => tx_buffer.avail -- data available when set
);
-- try to get new TX data --
tx_buffer.re <= '1' when (serial.state = S_IDLE) else '0';
-- Serial TX Engine -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
serial_engine: process(clk_i)
begin
if rising_edge(clk_i) then
-- clock generator --
serial.pulse_clk <= clkgen_i(to_integer(unsigned(ctrl.clk_prsc)));
-- defaults --
serial.done <= '0';
-- FSM --
if (ctrl.enable = '0') then -- disabled
serial.state <= S_IDLE;
else
case serial.state is
when S_IDLE => -- waiting for new TX data
-- ------------------------------------------------------------
serial.tx_out <= '0';
serial.pulse_cnt <= (others => '0');
serial.strobe_cnt <= (others => '0');
if (tx_buffer.avail = '1') then
serial.state <= S_INIT;
end if;
when S_INIT => -- initialize TX shift engine
-- ------------------------------------------------------------
if (tx_buffer.rdata(33) = '0') then -- send data
if (tx_buffer.rdata(32) = '0') then -- mode = "RGB"
serial.mode <= '0';
serial.bit_cnt <= "011000"; -- total number of bits to send: 3x8=24
else -- mode = "RGBW"
serial.mode <= '1';
serial.bit_cnt <= "100000"; -- total number of bits to send: 4x8=32
end if;
serial.sreg <= tx_buffer.rdata(31 downto 00);
serial.state <= S_GETBIT;
else -- send RESET command
serial.state <= S_STROBE;
end if;
when S_GETBIT => -- get next TX bit
-- ------------------------------------------------------------
serial.sreg <= serial.sreg(serial.sreg'left-1 downto 0) & '0'; -- shift left by one position (MSB-first)
serial.bit_cnt <= std_ulogic_vector(unsigned(serial.bit_cnt) - 1);
serial.pulse_cnt <= (others => '0');
if (serial.next_bit = '0') then -- send zero-bit
serial.t_high <= ctrl.t0_high;
else -- send one-bit
serial.t_high <= ctrl.t1_high;
end if;
if (serial.bit_cnt = "000000") then -- all done?
serial.tx_out <= '0';
serial.done <= '1'; -- done sending data
serial.state <= S_IDLE;
else -- send current data MSB
serial.tx_out <= '1';
serial.state <= S_PULSE; -- transmit single pulse
end if;
when S_PULSE => -- send pulse with specific duty cycle
-- ------------------------------------------------------------
-- total pulse length = ctrl.t_total
-- pulse high time = serial.t_high
if (serial.pulse_clk = '1') then
serial.pulse_cnt <= std_ulogic_vector(unsigned(serial.pulse_cnt) + 1);
-- T_high reached? --
if (serial.pulse_cnt = serial.t_high) then
serial.tx_out <= '0';
end if;
-- T_total reached? --
if (serial.pulse_cnt = ctrl.t_total) then
serial.state <= S_GETBIT; -- get next bit to send
end if;
end if;
when S_STROBE => -- strobe LED data ("RESET" command)
-- ------------------------------------------------------------
-- wait for 127 * ctrl.t_total to _ensure_ RESET
if (serial.pulse_clk = '1') then
-- T_total reached? --
if (serial.pulse_cnt = ctrl.t_total) then
serial.pulse_cnt <= (others => '0');
serial.strobe_cnt <= std_ulogic_vector(unsigned(serial.strobe_cnt) + 1);
else
serial.pulse_cnt <= std_ulogic_vector(unsigned(serial.pulse_cnt) + 1);
end if;
end if;
-- number of LOW periods reached for RESET? --
if (and_reduce_f(serial.strobe_cnt) = '1') then
serial.done <= '1'; -- done sending RESET
serial.state <= S_IDLE;
end if;
when others => -- undefined
-- ------------------------------------------------------------
serial.state <= S_IDLE;
end case;
end if;
-- serial data tx_out --
neoled_o <= serial.tx_out and ctrl.enable;
end if;
end process serial_engine;
-- SREG's TX data: bit 23 for RGB mode (24-bit), bit 31 for RGBW mode (32-bit) --
serial.next_bit <= serial.sreg(23) when (serial.mode = '0') else serial.sreg(31);
-- TX engine status --
serial.busy <= '0' when (serial.state = S_IDLE) else '1';
end neorv32_neoled_rtl;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,200 @@
-- #################################################################################################
-- # << NEORV32 - Pulse Width Modulation Controller (PWM) >> #
-- # ********************************************************************************************* #
-- # Simple PWM controller with 8 bit resolution for the duty cycle and programmable base #
-- # frequency. The controller supports up to 60 PWM channels. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_pwm is
generic (
NUM_CHANNELS : natural -- number of PWM channels (0..60)
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- pwm output channels --
pwm_o : out std_ulogic_vector(NUM_CHANNELS-1 downto 0)
);
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 NUM_CHANNELS-1) of std_ulogic_vector(7 downto 0);
signal pwm_ch : pwm_ch_t; -- duty cycle (r/w)
signal enable : std_ulogic; -- enable unit (r/w)
signal prsc : std_ulogic_vector(2 downto 0); -- clock prescaler (r/w)
type pwm_ch_rd_t is array (0 to 60-1) of std_ulogic_vector(7 downto 0);
signal pwm_ch_rd : pwm_ch_rd_t; -- duty cycle read-back
-- prescaler clock generator --
signal prsc_tick : std_ulogic;
-- pwm core counter --
signal pwm_cnt : std_ulogic_vector(7 downto 0);
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (NUM_CHANNELS > 60) report "NEORV32 PROCESSOR CONFIG ERROR! <IO.PWM> invalid number of channels! Has to be 0..60.!" severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
rden <= acc_en and rden_i;
wren <= acc_en and wren_i;
-- Write access ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
wr_access: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= rden or wren;
-- write access --
if (wren = '1') then
-- control register --
if (addr = pwm_ctrl_addr_c) then
enable <= data_i(ctrl_enable_c);
prsc <= data_i(ctrl_prsc2_bit_c downto ctrl_prsc0_bit_c);
end if;
-- duty cycle registers --
for i in 0 to NUM_CHANNELS-1 loop -- channel loop
if (addr(5 downto 2) = std_ulogic_vector(to_unsigned((i/4)+1, 4))) then -- 4 channels per register; add ctrl reg offset
pwm_ch(i) <= data_i((i mod 4)*8+7 downto (i mod 4)*8+0);
end if;
end loop;
end if;
-- read access --
data_o <= (others => '0');
if (rden = '1') then
case addr(5 downto 2) is
when x"0" => data_o(ctrl_enable_c) <= enable; data_o(ctrl_prsc2_bit_c downto ctrl_prsc0_bit_c) <= prsc;
when x"1" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(3) & pwm_ch_rd(2) & pwm_ch_rd(1) & pwm_ch_rd(0); else NULL; end if;
when x"2" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(7) & pwm_ch_rd(6) & pwm_ch_rd(5) & pwm_ch_rd(4); else NULL; end if;
when x"3" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(11) & pwm_ch_rd(10) & pwm_ch_rd(9) & pwm_ch_rd(8); else NULL; end if;
when x"4" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(15) & pwm_ch_rd(14) & pwm_ch_rd(13) & pwm_ch_rd(12); else NULL; end if;
when x"5" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(19) & pwm_ch_rd(18) & pwm_ch_rd(17) & pwm_ch_rd(16); else NULL; end if;
when x"6" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(23) & pwm_ch_rd(22) & pwm_ch_rd(21) & pwm_ch_rd(20); else NULL; end if;
when x"7" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(27) & pwm_ch_rd(26) & pwm_ch_rd(25) & pwm_ch_rd(24); else NULL; end if;
when x"8" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(31) & pwm_ch_rd(30) & pwm_ch_rd(29) & pwm_ch_rd(28); else NULL; end if;
when x"9" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(35) & pwm_ch_rd(34) & pwm_ch_rd(33) & pwm_ch_rd(32); else NULL; end if;
when x"a" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(39) & pwm_ch_rd(38) & pwm_ch_rd(37) & pwm_ch_rd(36); else NULL; end if;
when x"b" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(43) & pwm_ch_rd(42) & pwm_ch_rd(41) & pwm_ch_rd(40); else NULL; end if;
when x"c" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(47) & pwm_ch_rd(46) & pwm_ch_rd(45) & pwm_ch_rd(44); else NULL; end if;
when x"d" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(51) & pwm_ch_rd(50) & pwm_ch_rd(49) & pwm_ch_rd(48); else NULL; end if;
when x"e" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(55) & pwm_ch_rd(54) & pwm_ch_rd(53) & pwm_ch_rd(52); else NULL; end if;
when x"f" => if (NUM_CHANNELS > 0) then data_o <= pwm_ch_rd(59) & pwm_ch_rd(58) & pwm_ch_rd(57) & pwm_ch_rd(56); else NULL; end if;
when others => NULL;
end case;
end if;
end if;
end process wr_access;
-- duty cycle read-back --
pwm_dc_rd_gen: process(pwm_ch)
begin
pwm_ch_rd <= (others => (others => '0'));
for i in 0 to NUM_CHANNELS-1 loop
pwm_ch_rd(i) <= pwm_ch(i);
end loop;
end process pwm_dc_rd_gen;
-- PWM clock select --
clkgen_en_o <= enable; -- enable clock generator
prsc_tick <= clkgen_i(to_integer(unsigned(prsc)));
-- PWM Core -------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
pwm_core: process(clk_i)
begin
if rising_edge(clk_i) then
-- pwm base counter --
if (enable = '0') then
pwm_cnt <= (others => '0');
elsif (prsc_tick = '1') then
pwm_cnt <= std_ulogic_vector(unsigned(pwm_cnt) + 1);
end if;
-- channels --
for i in 0 to NUM_CHANNELS-1 loop
if (unsigned(pwm_cnt) >= unsigned(pwm_ch(i))) or (enable = '0') then
pwm_o(i) <= '0';
else
pwm_o(i) <= '1';
end if;
end loop;
end if;
end process pwm_core;
end neorv32_pwm_rtl;

View File

@ -0,0 +1,439 @@
-- #################################################################################################
-- # << NEORV32 - Stream Link Interface (SLINK) >> #
-- # ********************************************************************************************* #
-- # Up to 8 input (RX) and up to 8 output (TX) stream links are supported. Each link provides an #
-- # internal FIFO for buffering. Each stream direction provides a global interrupt to indicate #
-- # that a RX link has received new data or that a TX link has finished sending data #
-- # (if FIFO_DEPTH = 1) OR if RX/TX link FIFO has become half full (if FIFO_DEPTH > 1). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_slink is
generic (
SLINK_NUM_TX : natural; -- number of TX links (0..8)
SLINK_NUM_RX : natural; -- number of TX links (0..8)
SLINK_TX_FIFO : natural; -- TX fifo depth, has to be a power of two
SLINK_RX_FIFO : natural -- RX fifo depth, has to be a power of two
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- interrupt --
irq_tx_o : out std_ulogic; -- transmission done
irq_rx_o : out std_ulogic; -- data received
-- TX stream interfaces --
slink_tx_dat_o : out sdata_8x32_t; -- output data
slink_tx_val_o : out std_ulogic_vector(7 downto 0); -- valid output
slink_tx_rdy_i : in std_ulogic_vector(7 downto 0); -- ready to send
-- RX stream interfaces --
slink_rx_dat_i : in sdata_8x32_t; -- input data
slink_rx_val_i : in std_ulogic_vector(7 downto 0); -- valid input
slink_rx_rdy_o : out std_ulogic_vector(7 downto 0) -- ready to receive
);
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 bits --
constant ctrl_rx_num_lsb_c : natural := 0; -- r/-: number of implemented RX links
constant ctrl_rx_num_msb_c : natural := 3;
--
constant ctrl_tx_num_lsb_c : natural := 4; -- r/-: number of implemented TX links
constant ctrl_tx_num_msb_c : natural := 7;
--
constant ctrl_rx_size_lsb_c : natural := 8; -- r/-: log2(RX FIFO size)
constant ctrl_rx_size_msb_c : natural := 11;
--
constant ctrl_tx_size_lsb_c : natural := 12; -- r/-: log2(TX FIFO size)
constant ctrl_tx_size_msb_c : natural := 15;
--
constant ctrl_en_c : natural := 31; -- r/w: global enable
-- interrupt configuration register bits --
constant irq_rx_en_lsb_c : natural := 0; -- r/w: enable RX interrupt for link 0..7
constant irq_rx_en_msb_c : natural := 7;
--
constant irq_rx_mode_lsb_c : natural := 8; -- r/w: RX IRQ mode: 0=FIFO at least half-full; 1=FIFO not empty
constant irq_rx_mode_msb_c : natural := 15;
--
constant irq_tx_en_lsb_c : natural := 16; -- r/w: enable TX interrupt for link 0..7
constant irq_tx_en_msb_c : natural := 23;
--
constant irq_tx_mode_lsb_c : natural := 24; -- r/w: TX IRQ mode: 0=FIFO less than half-full; 1=FIFO not full
constant irq_tx_mode_msb_c : natural := 31;
-- status register bits --
constant status_rx_avail_lsb_c : natural := 0; -- r/-: set if RX link 0..7 FIFO is NOT empty
constant status_rx_avail_msb_c : natural := 7;
--
constant status_tx_free_lsb_c : natural := 8; -- r/-: set if TX link 0..7 FIFO is NOT full
constant status_tx_free_msb_c : natural := 15;
--
constant status_rx_half_lsb_c : natural := 16; -- r/-: set if RX link 0..7 FIFO fill-level is >= half-full
constant status_rx_half_msb_c : natural := 23;
--
constant status_tx_half_lsb_c : natural := 24; -- r/-: set if TX link 0..7 FIFO fill-level is > half-full
constant status_tx_half_msb_c : natural := 31;
-- bus access control --
signal ack_read : std_ulogic;
signal ack_write : std_ulogic;
signal acc_en : std_ulogic;
signal addr : std_ulogic_vector(31 downto 0);
signal wren : std_ulogic; -- word write enable
signal rden : std_ulogic; -- read enable
-- control register --
signal enable : std_ulogic; -- global enable
-- IRQ configuration register --
signal irq_rx_en : std_ulogic_vector(7 downto 0);
signal irq_rx_mode : std_ulogic_vector(7 downto 0);
signal irq_tx_en : std_ulogic_vector(7 downto 0);
signal irq_tx_mode : std_ulogic_vector(7 downto 0);
-- stream link fifo interface --
type fifo_data_t is array (0 to 7) of std_ulogic_vector(31 downto 0);
signal rx_fifo_rdata : fifo_data_t;
signal fifo_clear : std_ulogic;
signal link_sel : std_ulogic_vector(7 downto 0);
signal tx_fifo_we : std_ulogic_vector(7 downto 0);
signal rx_fifo_re : std_ulogic_vector(7 downto 0);
signal rx_fifo_avail : std_ulogic_vector(7 downto 0);
signal tx_fifo_free : std_ulogic_vector(7 downto 0);
signal rx_fifo_half : std_ulogic_vector(7 downto 0);
signal tx_fifo_half : std_ulogic_vector(7 downto 0);
-- interrupt generator --
type detect_t is array (0 to 7) of std_ulogic_vector(1 downto 0);
type irq_t is record
detect : detect_t; -- rising-edge detector
trigger : std_ulogic_vector(7 downto 0);
set : std_ulogic_vector(7 downto 0);
end record;
signal rx_irq, tx_irq : irq_t;
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (is_power_of_two_f(SLINK_TX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_TX_FIFO> has to be a power of two." severity error;
assert not (SLINK_TX_FIFO > 2**15) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_TX_FIFO> has to be 1..32768." severity error;
--
assert not (is_power_of_two_f(SLINK_RX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_RX_FIFO> has to be a power of two." severity error;
assert not (SLINK_RX_FIFO > 2**15) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_RX_FIFO> has to be 1..32768." severity error;
--
assert not (SLINK_NUM_RX > 8) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_NUM_RX> has to be 0..8." severity error;
assert not (SLINK_NUM_TX > 8) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_NUM_TX> has to be 0..8." severity error;
--
assert false report "NEORV32 PROCESSOR CONFIG NOTE: Implementing " & integer'image(SLINK_NUM_RX) & " RX and " &
integer'image(SLINK_NUM_TX) & " TX stream links." severity note;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = slink_base_c(hi_abb_c downto lo_abb_c)) else '0';
addr <= slink_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- write access --
ack_write <= '0';
if (wren = '1') then
if (addr(5) = '0') then -- control/status/irq
if (addr(4 downto 3) = "00") then -- control register
enable <= data_i(ctrl_en_c);
end if;
if (addr(4 downto 3) = "01") then -- IRQ configuration register
for i in 0 to SLINK_NUM_RX-1 loop
irq_rx_en(i) <= data_i(i + irq_rx_en_lsb_c);
irq_rx_mode(i) <= data_i(i + irq_rx_mode_lsb_c);
end loop;
for i in 0 to SLINK_NUM_TX-1 loop
irq_tx_en(i) <= data_i(i + irq_tx_en_lsb_c);
irq_tx_mode(i) <= data_i(i + irq_tx_mode_lsb_c);
end loop;
end if;
ack_write <= '1';
else -- TX links
ack_write <= or_reduce_f(link_sel and tx_fifo_free);
end if;
end if;
-- read access --
data_o <= (others => '0');
ack_read <= '0';
if (rden = '1') then
if (addr(5) = '0') then -- control/status registers
ack_read <= '1';
case addr(4 downto 3) is
when "00" => -- control register
data_o(ctrl_rx_num_msb_c downto ctrl_rx_num_lsb_c) <= std_ulogic_vector(to_unsigned(SLINK_NUM_RX, 4));
data_o(ctrl_tx_num_msb_c downto ctrl_tx_num_lsb_c) <= std_ulogic_vector(to_unsigned(SLINK_NUM_TX, 4));
data_o(ctrl_rx_size_msb_c downto ctrl_rx_size_lsb_c) <= std_ulogic_vector(to_unsigned(index_size_f(SLINK_RX_FIFO), 4));
data_o(ctrl_tx_size_msb_c downto ctrl_tx_size_lsb_c) <= std_ulogic_vector(to_unsigned(index_size_f(SLINK_TX_FIFO), 4));
data_o(ctrl_en_c) <= enable;
when "01" => -- IRQ configuration register
for i in 0 to SLINK_NUM_RX-1 loop
data_o(irq_rx_en_lsb_c + i) <= irq_rx_en(i);
data_o(irq_rx_mode_lsb_c + i) <= irq_rx_mode(i) or bool_to_ulogic_f(boolean(SLINK_RX_FIFO = 1)); -- tie to one if SLINK_RX_FIFO is 1
end loop;
for i in 0 to SLINK_NUM_TX-1 loop
data_o(irq_tx_en_lsb_c + i) <= irq_tx_en(i);
data_o(irq_tx_mode_lsb_c + i) <= irq_tx_mode(i) or bool_to_ulogic_f(boolean(SLINK_TX_FIFO = 1)); -- tie to one if SLINK_TX_FIFO is 1
end loop;
when "10" | "11" => -- fifo status register
data_o(status_rx_avail_msb_c downto status_rx_avail_lsb_c) <= rx_fifo_avail;
data_o(status_tx_free_msb_c downto status_tx_free_lsb_c) <= tx_fifo_free;
data_o(status_rx_half_msb_c downto status_rx_half_lsb_c) <= rx_fifo_half;
data_o(status_tx_half_msb_c downto status_tx_half_lsb_c) <= tx_fifo_half;
when others =>
data_o <= (others => '0');
end case;
else -- RX links
data_o <= rx_fifo_rdata(to_integer(unsigned(addr(4 downto 2))));
ack_read <= or_reduce_f(link_sel and rx_fifo_avail);
end if;
end if;
end if;
end process rw_access;
-- bus access acknowledge --
ack_o <= ack_write or ack_read;
-- link fifo reset (sync) --
fifo_clear <= not enable;
-- Interrupt Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- interrupt trigger type / condition --
irq_type: process(irq_rx_mode, rx_fifo_avail, rx_fifo_half, irq_tx_mode, tx_fifo_free, tx_fifo_half, tx_fifo_we)
begin
-- RX interrupt --
rx_irq.trigger <= (others => '0');
for i in 0 to SLINK_NUM_RX-1 loop
if (SLINK_RX_FIFO = 1) or (irq_rx_mode(i) = '0') then
rx_irq.trigger(i) <= rx_fifo_avail(i); -- fire if any RX_FIFO is not empty (= data available)
else
rx_irq.trigger(i) <= rx_fifo_half(i);
end if;
end loop;
-- TX interrupt --
tx_irq.trigger <= (others => '0');
for i in 0 to SLINK_NUM_TX-1 loop
if (SLINK_TX_FIFO = 1) or (irq_tx_mode(i) = '0') then
tx_irq.trigger(i) <= tx_fifo_free(i) and tx_fifo_we(i); -- fire if any TX_FIFO is not full (= free buffer space available)
else
tx_irq.trigger(i) <= not tx_fifo_half(i);
end if;
end loop;
end process irq_type;
-- edge detector - sync --
irq_edge_detect_sync: process(clk_i)
begin
if rising_edge(clk_i) then
-- RX --
for i in 0 to SLINK_NUM_RX-1 loop
if (enable = '1') and (irq_rx_en(i) = '1') then
rx_irq.detect(i) <= rx_irq.detect(i)(0) & rx_irq.trigger(i);
else
rx_irq.detect(i) <= "00";
end if;
end loop;
-- TX --
for i in 0 to SLINK_NUM_TX-1 loop
if (enable = '1') and (irq_tx_en(i) = '1') then
tx_irq.detect(i) <= tx_irq.detect(i)(0) & tx_irq.trigger(i);
else
tx_irq.detect(i) <= "00";
end if;
end loop;
end if;
end process irq_edge_detect_sync;
-- edge detector - sync --
irq_edge_detect_comb: process(rx_irq, irq_rx_en, tx_irq, irq_tx_en)
begin
-- RX --
rx_irq.set <= (others => '0');
for i in 0 to SLINK_NUM_RX-1 loop
if (rx_irq.detect(i) = "01") then -- rising-edge
rx_irq.set(i) <= '1';
end if;
end loop;
-- TX --
tx_irq.set <= (others => '0');
for i in 0 to SLINK_NUM_TX-1 loop
if (tx_irq.detect(i) = "01") then -- rising-edge
tx_irq.set(i) <= '1';
end if;
end loop;
end process irq_edge_detect_comb;
-- interrupt arbiter --
irq_generator: process(clk_i)
begin
if rising_edge(clk_i) then
irq_rx_o <= or_reduce_f(rx_irq.set);
irq_tx_o <= or_reduce_f(tx_irq.set);
end if;
end process irq_generator;
-- Link Select ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
link_select: process(addr)
begin
case addr(5 downto 2) is -- MSB = data fifo access at all?
when "1000" => link_sel <= "00000001";
when "1001" => link_sel <= "00000010";
when "1010" => link_sel <= "00000100";
when "1011" => link_sel <= "00001000";
when "1100" => link_sel <= "00010000";
when "1101" => link_sel <= "00100000";
when "1110" => link_sel <= "01000000";
when "1111" => link_sel <= "10000000";
when others => link_sel <= "00000000";
end case;
end process link_select;
fifo_access_gen:
for i in 0 to 7 generate
tx_fifo_we(i) <= link_sel(i) and wren;
rx_fifo_re(i) <= link_sel(i) and rden;
end generate;
-- TX Link FIFOs --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
transmit_fifo_gen:
for i in 0 to SLINK_NUM_TX-1 generate
transmit_fifo_inst: neorv32_fifo
generic map (
FIFO_DEPTH => SLINK_TX_FIFO, -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH => 32, -- size of data elements in fifo
FIFO_RSYNC => false, -- async read
FIFO_SAFE => true -- safe access
)
port map (
-- control --
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => fifo_clear, -- sync reset, high-active
level_o => open, -- fill level
half_o => tx_fifo_half(i), -- FIFO is at least half full
-- write port --
wdata_i => data_i, -- write data
we_i => tx_fifo_we(i), -- write enable
free_o => tx_fifo_free(i), -- at least one entry is free when set
-- read port --
re_i => slink_tx_rdy_i(i), -- read enable
rdata_o => slink_tx_dat_o(i), -- read data
avail_o => slink_tx_val_o(i) -- data available when set
);
end generate;
-- terminate unimplemented links --
transmit_fifo_gen_terminate:
for i in SLINK_NUM_TX to 7 generate
tx_fifo_free(i) <= '0';
slink_tx_dat_o(i) <= (others => '0');
slink_tx_val_o(i) <= '0';
tx_fifo_half(i) <= '0';
end generate;
-- RX Link FIFOs --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
receive_fifo_gen:
for i in 0 to SLINK_NUM_RX-1 generate
receive_fifo_inst: neorv32_fifo
generic map (
FIFO_DEPTH => SLINK_RX_FIFO, -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH => 32, -- size of data elements in fifo
FIFO_RSYNC => false, -- async read
FIFO_SAFE => true -- safe access
)
port map (
-- control --
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => fifo_clear, -- sync reset, high-active
level_o => open, -- fill level
half_o => rx_fifo_half(i), -- FIFO is at least half full
-- write port --
wdata_i => slink_rx_dat_i(i), -- write data
we_i => slink_rx_val_i(i), -- write enable
free_o => slink_rx_rdy_o(i), -- at least one entry is free when set
-- read port --
re_i => rx_fifo_re(i), -- read enable
rdata_o => rx_fifo_rdata(i), -- read data
avail_o => rx_fifo_avail(i) -- data available when set
);
end generate;
-- terminate unimplemented links --
receive_fifo_gen_terminate:
for i in SLINK_NUM_RX to 7 generate
rx_fifo_avail(i) <= '0';
slink_rx_rdy_o(i) <= '0';
rx_fifo_rdata(i) <= (others => '0');
rx_fifo_half(i) <= '0';
end generate;
end neorv32_slink_rtl;

View File

@ -0,0 +1,287 @@
-- #################################################################################################
-- # << NEORV32 - Serial Peripheral Interface Controller (SPI) >> #
-- # ********************************************************************************************* #
-- # Frame format: 8/16/24/32-bit receive/transmit data, always MSB first, 2 clock modes, #
-- # 8 pre-scaled clocks (derived from system clock), 8 dedicated chip-select lines (low-active). #
-- # Interrupt: "transfer done" #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_spi is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- com lines --
spi_sck_o : out std_ulogic; -- SPI serial clock
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in
spi_sdi_i : in std_ulogic; -- controller data in, peripheral data out
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS
-- interrupt --
irq_o : out std_ulogic -- transmission done interrupt
);
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_cs0_c : natural := 0; -- r/w: spi CS 0
constant ctrl_cs1_c : natural := 1; -- r/w: spi CS 1
constant ctrl_cs2_c : natural := 2; -- r/w: spi CS 2
constant ctrl_cs3_c : natural := 3; -- r/w: spi CS 3
constant ctrl_cs4_c : natural := 4; -- r/w: spi CS 4
constant ctrl_cs5_c : natural := 5; -- r/w: spi CS 5
constant ctrl_cs6_c : natural := 6; -- r/w: spi CS 6
constant ctrl_cs7_c : natural := 7; -- r/w: spi CS 7
--
constant ctrl_en_c : natural := 8; -- r/w: spi enable
constant ctrl_cpha_c : natural := 9; -- r/w: spi clock phase
constant ctrl_prsc0_c : natural := 10; -- r/w: spi prescaler select bit 0
constant ctrl_prsc1_c : natural := 11; -- r/w: spi prescaler select bit 1
constant ctrl_prsc2_c : natural := 12; -- r/w: spi prescaler select bit 2
constant ctrl_size0_c : natural := 13; -- r/w: data size lsb (00: 8-bit, 01: 16-bit)
constant ctrl_size1_c : natural := 14; -- r/w: data size msb (10: 24-bit, 11: 32-bit)
constant ctrl_cpol_c : natural := 15; -- r/w: spi clock polarity
--
constant ctrl_busy_c : natural := 31; -- r/-: spi transceiver is busy
--
signal ctrl : std_ulogic_vector(15 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
-- clock generator --
signal spi_clk_en : std_ulogic;
-- spi transceiver --
type rtx_engine_t is record
state : std_ulogic_vector(02 downto 0);
busy : std_ulogic;
start : std_ulogic;
sreg : std_ulogic_vector(31 downto 0);
bitcnt : std_ulogic_vector(05 downto 0);
bytecnt : std_ulogic_vector(02 downto 0);
sdi_sync : std_ulogic_vector(01 downto 0);
end record;
signal rtx_engine : rtx_engine_t;
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- bus access acknowledge --
ack_o <= rden or wren;
-- write access --
if (wren = '1') then
if (addr = spi_ctrl_addr_c) then -- control register
ctrl(ctrl_cs0_c) <= data_i(ctrl_cs0_c);
ctrl(ctrl_cs1_c) <= data_i(ctrl_cs1_c);
ctrl(ctrl_cs2_c) <= data_i(ctrl_cs2_c);
ctrl(ctrl_cs3_c) <= data_i(ctrl_cs3_c);
ctrl(ctrl_cs4_c) <= data_i(ctrl_cs4_c);
ctrl(ctrl_cs5_c) <= data_i(ctrl_cs5_c);
ctrl(ctrl_cs6_c) <= data_i(ctrl_cs6_c);
ctrl(ctrl_cs7_c) <= data_i(ctrl_cs7_c);
--
ctrl(ctrl_en_c) <= data_i(ctrl_en_c);
ctrl(ctrl_cpha_c) <= data_i(ctrl_cpha_c);
ctrl(ctrl_prsc0_c) <= data_i(ctrl_prsc0_c);
ctrl(ctrl_prsc1_c) <= data_i(ctrl_prsc1_c);
ctrl(ctrl_prsc2_c) <= data_i(ctrl_prsc2_c);
ctrl(ctrl_size0_c) <= data_i(ctrl_size0_c);
ctrl(ctrl_size1_c) <= data_i(ctrl_size1_c);
ctrl(ctrl_cpol_c) <= data_i(ctrl_cpol_c);
end if;
end if;
-- read access --
data_o <= (others => '0');
if (rden = '1') then
if (addr = spi_ctrl_addr_c) then -- control register
data_o(ctrl_cs0_c) <= ctrl(ctrl_cs0_c);
data_o(ctrl_cs1_c) <= ctrl(ctrl_cs1_c);
data_o(ctrl_cs2_c) <= ctrl(ctrl_cs2_c);
data_o(ctrl_cs3_c) <= ctrl(ctrl_cs3_c);
data_o(ctrl_cs4_c) <= ctrl(ctrl_cs4_c);
data_o(ctrl_cs5_c) <= ctrl(ctrl_cs5_c);
data_o(ctrl_cs6_c) <= ctrl(ctrl_cs6_c);
data_o(ctrl_cs7_c) <= ctrl(ctrl_cs7_c);
--
data_o(ctrl_en_c) <= ctrl(ctrl_en_c);
data_o(ctrl_cpha_c) <= ctrl(ctrl_cpha_c);
data_o(ctrl_prsc0_c) <= ctrl(ctrl_prsc0_c);
data_o(ctrl_prsc1_c) <= ctrl(ctrl_prsc1_c);
data_o(ctrl_prsc2_c) <= ctrl(ctrl_prsc2_c);
data_o(ctrl_size0_c) <= ctrl(ctrl_size0_c);
data_o(ctrl_size1_c) <= ctrl(ctrl_size1_c);
data_o(ctrl_cpol_c) <= ctrl(ctrl_cpol_c);
--
data_o(ctrl_busy_c) <= rtx_engine.busy;
else -- data register (spi_rtx_addr_c)
data_o <= rtx_engine.sreg;
end if;
end if;
end if;
end process rw_access;
-- direct chip-select (CS), output is low-active --
spi_csn_o(7 downto 0) <= not ctrl(ctrl_cs7_c downto ctrl_cs0_c);
-- trigger new SPI transmission --
rtx_engine.start <= '1' when (wren = '1') and (addr = spi_rtx_addr_c) else '0';
-- Clock Selection ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
clkgen_en_o <= ctrl(ctrl_en_c); -- clock generator enable
spi_clk_en <= clkgen_i(to_integer(unsigned(ctrl(ctrl_prsc2_c downto ctrl_prsc0_c)))); -- clock select
-- Transmission Data Size -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
data_size: process(ctrl)
begin
case ctrl(ctrl_size1_c downto ctrl_size0_c) is
when "00" => rtx_engine.bytecnt <= "001"; -- 1-byte mode
when "01" => rtx_engine.bytecnt <= "010"; -- 2-byte mode
when "10" => rtx_engine.bytecnt <= "011"; -- 3-byte mode
when others => rtx_engine.bytecnt <= "100"; -- 4-byte mode
end case;
end process data_size;
-- SPI Transceiver ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
spi_rtx_unit: process(clk_i)
begin
if rising_edge(clk_i) then
-- input (sdi) synchronizer --
rtx_engine.sdi_sync <= rtx_engine.sdi_sync(0) & spi_sdi_i;
-- output (sdo) buffer --
case ctrl(ctrl_size1_c downto ctrl_size0_c) is
when "00" => spi_sdo_o <= rtx_engine.sreg(07); -- 8-bit mode
when "01" => spi_sdo_o <= rtx_engine.sreg(15); -- 16-bit mode
when "10" => spi_sdo_o <= rtx_engine.sreg(23); -- 24-bit mode
when others => spi_sdo_o <= rtx_engine.sreg(31); -- 32-bit mode
end case;
-- defaults --
spi_sck_o <= ctrl(ctrl_cpol_c);
irq_o <= '0';
-- serial engine --
rtx_engine.state(2) <= ctrl(ctrl_en_c);
case rtx_engine.state is
when "100" => -- enabled but idle, waiting for new transmission trigger
-- ------------------------------------------------------------
rtx_engine.bitcnt <= (others => '0');
if (rtx_engine.start = '1') then -- trigger new transmission
rtx_engine.sreg <= data_i;
rtx_engine.state(1 downto 0) <= "01";
end if;
when "101" => -- start with next new clock pulse
-- ------------------------------------------------------------
if (spi_clk_en = '1') then
rtx_engine.state(1 downto 0) <= "10";
end if;
when "110" => -- first half of bit transmission
-- ------------------------------------------------------------
spi_sck_o <= ctrl(ctrl_cpha_c) xor ctrl(ctrl_cpol_c);
if (spi_clk_en = '1') then
rtx_engine.bitcnt <= std_ulogic_vector(unsigned(rtx_engine.bitcnt) + 1);
rtx_engine.state(1 downto 0) <= "11";
end if;
when "111" => -- second half of bit transmission
-- ------------------------------------------------------------
spi_sck_o <= ctrl(ctrl_cpha_c) xnor ctrl(ctrl_cpol_c);
if (spi_clk_en = '1') then
rtx_engine.sreg <= rtx_engine.sreg(30 downto 0) & rtx_engine.sdi_sync(rtx_engine.sdi_sync'left);
if (rtx_engine.bitcnt(5 downto 3) = rtx_engine.bytecnt) then -- all bits transferred?
irq_o <= '1'; -- interrupt!
rtx_engine.state(1 downto 0) <= "00"; -- transmission done
else
rtx_engine.state(1 downto 0) <= "10";
end if;
end if;
when others => -- "0--": SPI deactivated
-- ------------------------------------------------------------
rtx_engine.state(1 downto 0) <= "00";
end case;
end if;
end process spi_rtx_unit;
-- busy flag --
rtx_engine.busy <= '0' when (rtx_engine.state(1 downto 0) = "00") else '1';
end neorv32_spi_rtl;

View File

@ -0,0 +1,227 @@
-- #################################################################################################
-- # << NEORV32 - System/Processor Configuration Information Memory (SYSINFO) >> #
-- # ********************************************************************************************* #
-- # This unit provides information regarding the NEORV32 processor system configuration - #
-- # mostly derived from the top's configuration generics. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_sysinfo is
generic (
-- General --
CLOCK_FREQUENCY : natural; -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN : boolean; -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr : boolean; -- implement base counters?
CPU_EXTENSION_RISCV_Zihpm : boolean; -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
CPU_EXTENSION_RISCV_Zmmul : boolean; -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_DEBUG : boolean; -- implement CPU debug mode?
-- Extension Options --
FAST_MUL_EN : boolean; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural; -- total width of CPU cycle and instret counters (0..64)
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
-- 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
-- Internal Cache memory --
ICACHE_EN : boolean; -- implement instruction cache
ICACHE_NUM_BLOCKS : natural; -- i-cache: number of blocks (min 2), has to be a power of 2
ICACHE_BLOCK_SIZE : natural; -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY : natural; -- i-cache: associativity (min 1), has to be a power 2
-- External memory interface --
MEM_EXT_EN : boolean; -- implement external memory bus interface?
MEM_EXT_BIG_ENDIAN : boolean; -- byte order: true=big-endian, false=little-endian
-- On-Chip Debugger --
ON_CHIP_DEBUGGER_EN : boolean; -- implement OCD?
-- Processor peripherals --
IO_GPIO_EN : boolean; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART1_EN : boolean; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_SPI_EN : boolean; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural; -- number of PWM channels to implement
IO_WDT_EN : boolean; -- implement watch dog timer (WDT)?
IO_TRNG_EN : boolean; -- implement true random number generator (TRNG)?
IO_CFS_EN : boolean; -- implement custom functions subsystem (CFS)?
IO_SLINK_EN : boolean; -- implement stream link interface?
IO_NEOLED_EN : boolean; -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_XIRQ_NUM_CH : natural; -- number of external interrupt (XIRQ) channels to implement
IO_GPTMR_EN : boolean -- implement general purpose timer (GPTMR)?
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic -- transfer acknowledge
);
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 addr : std_ulogic_vector(31 downto 0);
signal rden : std_ulogic;
signal info_addr : std_ulogic_vector(02 downto 0);
-- system information ROM --
type info_mem_t is array (0 to 7) of std_ulogic_vector(31 downto 0);
signal sysinfo_mem : info_mem_t;
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = sysinfo_base_c(hi_abb_c downto lo_abb_c)) else '0';
rden <= acc_en and rden_i; -- valid read access
addr <= sysinfo_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
info_addr <= addr(index_size_f(sysinfo_size_c)-1 downto 2);
-- Construct Info ROM ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- SYSINFO(0): Processor (primary) clock frequency --
sysinfo_mem(0) <= std_ulogic_vector(to_unsigned(CLOCK_FREQUENCY, 32));
-- SYSINFO(1): CPU configuration --
sysinfo_mem(1)(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr
sysinfo_mem(1)(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei
sysinfo_mem(1)(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zmmul); -- Zmmul
--
sysinfo_mem(1)(04 downto 03) <= (others => '0'); -- reserved
--
sysinfo_mem(1)(05) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- Zfinx ("F-alternative")
sysinfo_mem(1)(06) <= bool_to_ulogic_f(boolean(CPU_CNT_WIDTH /= 64)); -- reduced-size CPU counters (Zxscnt)
sysinfo_mem(1)(07) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr); -- base CPU counter
sysinfo_mem(1)(08) <= bool_to_ulogic_f(boolean(PMP_NUM_REGIONS > 0)); -- PMP (physical memory protection)
sysinfo_mem(1)(09) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- HPM (hardware performance monitors)
sysinfo_mem(1)(10) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG); -- RISC-V debug mode
--
sysinfo_mem(1)(29 downto 11) <= (others => '0'); -- reserved
-- misc --
sysinfo_mem(1)(30) <= bool_to_ulogic_f(FAST_MUL_EN); -- DSP-based multiplication (M extension only)
sysinfo_mem(1)(31) <= bool_to_ulogic_f(FAST_SHIFT_EN); -- parallel logic for shifts (like barrel shifters)
-- SYSINFO(2): Implemented processor devices/features --
-- Memory --
sysinfo_mem(2)(00) <= bool_to_ulogic_f(INT_BOOTLOADER_EN); -- processor-internal bootloader implemented?
sysinfo_mem(2)(01) <= bool_to_ulogic_f(MEM_EXT_EN); -- external memory bus interface implemented?
sysinfo_mem(2)(02) <= bool_to_ulogic_f(MEM_INT_IMEM_EN) and bool_to_ulogic_f(boolean(MEM_INT_IMEM_SIZE > 0)); -- processor-internal instruction memory implemented?
sysinfo_mem(2)(03) <= bool_to_ulogic_f(MEM_INT_DMEM_EN) and bool_to_ulogic_f(boolean(MEM_INT_DMEM_SIZE > 0)); -- processor-internal data memory implemented?
sysinfo_mem(2)(04) <= bool_to_ulogic_f(MEM_EXT_BIG_ENDIAN); -- is external memory bus interface using BIG-endian byte-order?
sysinfo_mem(2)(05) <= bool_to_ulogic_f(ICACHE_EN); -- processor-internal instruction cache implemented?
--
sysinfo_mem(2)(12 downto 06) <= (others => '0'); -- reserved
-- Misc --
sysinfo_mem(2)(13) <= bool_to_ulogic_f(is_simulation_c); -- is this a simulation?
sysinfo_mem(2)(14) <= bool_to_ulogic_f(ON_CHIP_DEBUGGER_EN); -- on-chip debugger implemented?
sysinfo_mem(2)(15) <= bool_to_ulogic_f(dedicated_reset_c); -- dedicated hardware reset of all core registers?
-- IO --
sysinfo_mem(2)(16) <= bool_to_ulogic_f(IO_GPIO_EN); -- general purpose input/output port unit (GPIO) implemented?
sysinfo_mem(2)(17) <= bool_to_ulogic_f(IO_MTIME_EN); -- machine system timer (MTIME) implemented?
sysinfo_mem(2)(18) <= bool_to_ulogic_f(IO_UART0_EN); -- primary universal asynchronous receiver/transmitter (UART0) implemented?
sysinfo_mem(2)(19) <= bool_to_ulogic_f(IO_SPI_EN); -- serial peripheral interface (SPI) implemented?
sysinfo_mem(2)(20) <= bool_to_ulogic_f(IO_TWI_EN); -- two-wire interface (TWI) implemented?
sysinfo_mem(2)(21) <= bool_to_ulogic_f(boolean(IO_PWM_NUM_CH > 0)); -- pulse-width modulation unit (PWM) implemented?
sysinfo_mem(2)(22) <= bool_to_ulogic_f(IO_WDT_EN); -- watch dog timer (WDT) implemented?
sysinfo_mem(2)(23) <= bool_to_ulogic_f(IO_CFS_EN); -- custom functions subsystem (CFS) implemented?
sysinfo_mem(2)(24) <= bool_to_ulogic_f(IO_TRNG_EN); -- true random number generator (TRNG) implemented?
sysinfo_mem(2)(25) <= bool_to_ulogic_f(IO_SLINK_EN); -- stream links (SLINK) implemented?
sysinfo_mem(2)(26) <= bool_to_ulogic_f(IO_UART1_EN); -- secondary universal asynchronous receiver/transmitter (UART1) implemented?
sysinfo_mem(2)(27) <= bool_to_ulogic_f(IO_NEOLED_EN); -- NeoPixel-compatible smart LED interface (NEOLED) implemented?
sysinfo_mem(2)(28) <= bool_to_ulogic_f(boolean(IO_XIRQ_NUM_CH > 0)); -- external interrupt controller (XIRQ) implemented?
sysinfo_mem(2)(29) <= bool_to_ulogic_f(IO_GPTMR_EN); -- general purpose timer (GPTMR) implemented?
--
sysinfo_mem(2)(31 downto 30) <= (others => '0'); -- reserved
-- SYSINFO(3): Cache configuration --
sysinfo_mem(3)(03 downto 00) <= std_ulogic_vector(to_unsigned(index_size_f(ICACHE_BLOCK_SIZE), 4)) when (ICACHE_EN = true) else (others => '0'); -- i-cache: log2(block_size_in_bytes)
sysinfo_mem(3)(07 downto 04) <= std_ulogic_vector(to_unsigned(index_size_f(ICACHE_NUM_BLOCKS), 4)) when (ICACHE_EN = true) else (others => '0'); -- i-cache: log2(number_of_block)
sysinfo_mem(3)(11 downto 08) <= std_ulogic_vector(to_unsigned(index_size_f(ICACHE_ASSOCIATIVITY), 4)) when (ICACHE_EN = true) else (others => '0'); -- i-cache: log2(associativity)
sysinfo_mem(3)(15 downto 12) <= "0001" when (ICACHE_ASSOCIATIVITY > 1) and (ICACHE_EN = true) else (others => '0'); -- i-cache: replacement strategy (LRU only (yet))
--
sysinfo_mem(3)(19 downto 16) <= (others => '0'); -- reserved - d-cache: log2(block_size)
sysinfo_mem(3)(23 downto 20) <= (others => '0'); -- reserved - d-cache: log2(num_blocks)
sysinfo_mem(3)(27 downto 24) <= (others => '0'); -- reserved - d-cache: log2(associativity)
sysinfo_mem(3)(31 downto 28) <= (others => '0'); -- reserved - d-cache: replacement strategy
-- SYSINFO(4): Base address of instruction memory space --
sysinfo_mem(4) <= ispace_base_c; -- defined in neorv32_package.vhd file
-- SYSINFO(5): Base address of data memory space --
sysinfo_mem(5) <= dspace_base_c; -- defined in neorv32_package.vhd file
-- SYSINFO(6): Size of IMEM in bytes --
sysinfo_mem(6) <= std_ulogic_vector(to_unsigned(MEM_INT_IMEM_SIZE, 32)) when (MEM_INT_IMEM_EN = true) else (others => '0');
-- SYSINFO(7): Size of DMEM in bytes --
sysinfo_mem(7) <= std_ulogic_vector(to_unsigned(MEM_INT_DMEM_SIZE, 32)) when (MEM_INT_DMEM_EN = true) else (others => '0');
-- Read Access ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
read_access: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= rden;
data_o <= (others => '0');
if (rden = '1') then
data_o <= sysinfo_mem(to_integer(unsigned(info_addr)));
end if;
end if;
end process read_access;
end neorv32_sysinfo_rtl;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,550 @@
-- #################################################################################################
-- # << NEORV32 - True Random Number Generator (TRNG) >> #
-- # ********************************************************************************************* #
-- # This processor module instantiates the "neoTRNG" true random number generator. #
-- # See the neoTRNG's documentation for more information: https://github.com/stnolting/neoTRNG #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_trng is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic -- transfer acknowledge
);
end neorv32_trng;
architecture neorv32_trng_rtl of neorv32_trng is
-- neoTRNG Configuration -------------------------------------------------------------------------------------------
constant num_cells_c : natural := 3; -- total number of ring-oscillator cells
constant num_inv_start_c : natural := 3; -- number of inverters in first cell (short path), has to be odd
constant num_inv_inc_c : natural := 2; -- number of additional inverters in next cell (short path), has to be even
constant num_inv_delay_c : natural := 2; -- additional inverters to form cell's long path, has to be even
-- -----------------------------------------------------------------------------------------------------------------
-- control register bits --
constant ctrl_data_lsb_c : natural := 0; -- r/-: Random data byte LSB
constant ctrl_data_msb_c : natural := 7; -- r/-: Random data byte MSB
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 (
NUM_CELLS : natural; -- total number of ring-oscillator cells
NUM_INV_START : natural; -- number of inverters in first cell (short path), has to be odd
NUM_INV_INC : natural; -- number of additional inverters in next cell (short path), has to be even
NUM_INV_DELAY : natural -- additional inverters to form cell's long path, has to be even
);
port (
clk_i : in std_ulogic; -- global clock line
enable_i : in std_ulogic; -- unit enable (high-active), reset unit when low
data_o : out std_ulogic_vector(7 downto 0); -- random data byte output
valid_o : out std_ulogic -- data_o is valid when set
);
end component;
-- TRNG interface --
signal trng_data : std_ulogic_vector(7 downto 0);
signal trng_valid : std_ulogic;
-- arbiter --
signal enable : std_ulogic;
signal valid : std_ulogic;
signal rnd_reg : std_ulogic_vector(7 downto 0);
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = trng_base_c(hi_abb_c downto lo_abb_c)) else '0';
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- host bus acknowledge --
ack_o <= wren or rden;
-- write access --
if (wren = '1') then
enable <= data_i(ctrl_en_c);
end if;
-- read access --
data_o <= (others => '0');
if (rden = '1') then
data_o(ctrl_data_msb_c downto ctrl_data_lsb_c) <= rnd_reg;
data_o(ctrl_en_c) <= enable;
data_o(ctrl_valid_c) <= valid;
end if;
-- sample --
if (trng_valid = '1') then
rnd_reg <= trng_data;
end if;
-- data valid? --
if (enable = '0') then -- disabled
valid <= '0';
else
if (trng_valid = '1') then
valid <= '1';
elsif (rden = '1') then
valid <= '0';
end if;
end if;
end if;
end process rw_access;
-- neoTRNG --------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neoTRNG_inst: neoTRNG
generic map (
NUM_CELLS => num_cells_c,
NUM_INV_START => num_inv_start_c,
NUM_INV_INC => num_inv_inc_c,
NUM_INV_DELAY => num_inv_delay_c
)
port map (
clk_i => clk_i,
enable_i => enable,
data_o => trng_data,
valid_o => trng_valid
);
end neorv32_trng_rtl;
-- ############################################################################################################################
-- ############################################################################################################################
-- #################################################################################################
-- # << neoTRNG - A Tiny and Platform-Independent True Random Number Generator for any FPGA >> #
-- # ********************************************************************************************* #
-- # This generator is based on entropy cells, which implement simple ring-oscillators. Each ring- #
-- # oscillator features a short and a long delay path that is dynamically selected defining the #
-- # primary oscillation frequency. The cells are cascaded so that the random data output of a #
-- # cell controls the delay path of the next cell (which has the next-larger inverter chain). #
-- # #
-- # The random data outputs of all cells are XOR-ed and de-biased using a von Neumann randomness #
-- # extractor (converting edges into bits). The resulting bit is sampled in chunks of 8 bits to #
-- # provide the final random data output. No further internal post-processing is applied. Hence, #
-- # the TRNG produces simple de-biased *RAW* data. #
-- # #
-- # The entropy cell architecture uses individually-controlled latches and inverters to create #
-- # the inverter chain in a platform-agnostic style that can be implemented for any FPGA without #
-- # requiring primitive instantiation or technology-specific attributes. #
-- # #
-- # See the neoTRNG's documentation for more information: https://github.com/stnolting/neoTRNG #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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. #
-- # ********************************************************************************************* #
-- # neoTRNG - https://github.com/stnolting/neoTRNG (c) Stephan Nolting #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity neoTRNG is
generic (
NUM_CELLS : natural; -- total number of ring-oscillator cells
NUM_INV_START : natural; -- number of inverters in first cell (short path), has to be odd
NUM_INV_INC : natural; -- number of additional inverters in next cell (short path), has to be even
NUM_INV_DELAY : natural -- additional inverters to form cell's long path, has to be even
);
port (
clk_i : in std_ulogic; -- global clock line
enable_i : in std_ulogic; -- unit enable (high-active), reset unit when low
data_o : out std_ulogic_vector(7 downto 0); -- random data byte output
valid_o : out std_ulogic -- data_o is valid when set
);
end neoTRNG;
architecture neoTRNG_rtl of neoTRNG is
-- Component: neoTRNG entropy cell --
component neoTRNG_cell
generic (
NUM_INV_S : natural; -- number of inverters in short path
NUM_INV_L : natural -- number of inverters in long path
);
port (
clk_i : in std_ulogic; -- system clock
select_i : in std_ulogic; -- delay select
enable_i : in std_ulogic; -- enable chain input
enable_o : out std_ulogic; -- enable chain output
data_o : out std_ulogic -- sync random bit
);
end component;
-- ring-oscillator array interconnect --
type cell_array_t is record
en_in : std_ulogic_vector(NUM_CELLS-1 downto 0);
en_out : std_ulogic_vector(NUM_CELLS-1 downto 0);
rnd : std_ulogic_vector(NUM_CELLS-1 downto 0);
sel : std_ulogic_vector(NUM_CELLS-1 downto 0);
end record;
signal cell_array : cell_array_t;
-- global cell-XOR --
signal rnd_bit : std_ulogic;
-- von-Neumann de-biasing --
type debiasing_t is record
sreg : std_ulogic_vector(1 downto 0);
state : std_ulogic; -- process de-biasing every second cycle
valid : std_ulogic; -- de-biased data
data : std_ulogic; -- de-biased data valid
end record;
signal deb : debiasing_t;
-- control unit --
type ctrl_t is record
enable : std_ulogic;
run : std_ulogic;
cnt : std_ulogic_vector(2 downto 0); -- bit counter
sreg : std_ulogic_vector(7 downto 0); -- data shift register
end record;
signal ctrl : ctrl_t;
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (NUM_CELLS < 2) report "neoTRNG config ERROR: Total number of ring-oscillator cells <NUM_CELLS> has to be >= 2." severity error;
assert not ((NUM_INV_START mod 2) = 0) report "neoTRNG config ERROR: Number of inverters in first cell <NUM_INV_START> has to be odd." severity error;
assert not ((NUM_INV_INC mod 2) /= 0) report "neoTRNG config ERROR: Inverter increment for each next cell <NUM_INV_INC> has to be even." severity error;
assert not ((NUM_INV_DELAY mod 2) /= 0) report "neoTRNG config ERROR: Inverter increment to form long path <NUM_INV_DELAY> has to be even." severity error;
-- Entropy Source -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neoTRNG_cell_inst:
for i in 0 to NUM_CELLS-1 generate
neoTRNG_cell_inst_i: neoTRNG_cell
generic map (
NUM_INV_S => NUM_INV_START + (i*NUM_INV_INC), -- number of inverters in short chain
NUM_INV_L => NUM_INV_START + (i*NUM_INV_INC) + NUM_INV_DELAY -- number of inverters in long chain
)
port map (
clk_i => clk_i,
select_i => cell_array.sel(i),
enable_i => cell_array.en_in(i),
enable_o => cell_array.en_out(i),
data_o => cell_array.rnd(i) -- SYNC data output
);
end generate;
-- path select chain --
cell_array.sel(0) <= cell_array.rnd(NUM_CELLS-1); -- use output of last cell to select path of first cell
cell_array.sel(NUM_CELLS-1 downto 1) <= cell_array.rnd(NUM_CELLS-2 downto 0); -- i+1 <= i
-- enable chain --
cell_array.en_in(0) <= ctrl.enable; -- start of chain
cell_array.en_in(NUM_CELLS-1 downto 1) <=cell_array.en_out(NUM_CELLS-2 downto 0); -- i+1 <= i
-- XOR All Cell's Outputs -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
cell_xor: process(cell_array.rnd)
variable tmp_v : std_ulogic;
begin
tmp_v := '0';
for i in 0 to NUM_CELLS-1 loop
tmp_v := tmp_v xor cell_array.rnd(i);
end loop; -- i
rnd_bit <= tmp_v;
end process cell_xor;
-- John von Neumann Randomness Extractor --------------------------------------------------
-- -------------------------------------------------------------------------------------------
debiasing_sync: process(clk_i)
begin
if rising_edge(clk_i) then
deb.sreg <= deb.sreg(0) & rnd_bit;
-- start operation when last cell is enabled and process in every second cycle --
deb.state <= (not deb.state) and cell_array.en_out(NUM_CELLS-1);
end if;
end process debiasing_sync;
-- edge detector --
debiasing_comb: process(deb)
variable tmp_v : std_ulogic_vector(2 downto 0);
begin
tmp_v := deb.state & deb.sreg(1 downto 0); -- check groups of two non-overlapping bits from the input stream
case tmp_v is
when "101" => deb.valid <= '1'; deb.data <= '0'; -- rising edge = '0'
when "110" => deb.valid <= '1'; deb.data <= '1'; -- falling edge = '1'
when others => deb.valid <= '0'; deb.data <= '-'; -- no valid data
end case;
end process debiasing_comb;
-- Control Unit ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
control_unit: process(clk_i)
begin
if rising_edge(clk_i) then
-- make sure enable is sync --
ctrl.enable <= enable_i;
-- sample chunks of 8 bit --
if (ctrl.enable = '0') then
ctrl.cnt <= (others => '0');
ctrl.run <= '0';
elsif (deb.valid = '1') then -- valid random sample?
ctrl.cnt <= std_ulogic_vector(unsigned(ctrl.cnt) + 1);
ctrl.run <= '1';
end if;
-- sample shift register --
if (deb.valid = '1') then
ctrl.sreg <= ctrl.sreg(ctrl.sreg'left-1 downto 0) & deb.data;
end if;
end if;
end process control_unit;
-- random byte output --
data_o <= ctrl.sreg;
-- data valid? --
valid_o <= '1' when (ctrl.cnt = "000") and (ctrl.run = '1') else '0';
end neoTRNG_rtl;
-- ############################################################################################################################
-- ############################################################################################################################
-- #################################################################################################
-- # << neoTRNG - A Tiny and Platform-Independent True Random Number Generator for any FPGA >> #
-- # ********************************************************************************************* #
-- # neoTRNG Entropy Cell #
-- # #
-- # The cell consists of two ring-oscillators build from inverter chains. The short chain uses #
-- # NUM_INV_S inverters and oscillates at a "high" frequency and the long chain uses NUM_INV_L #
-- # inverters and oscillates at a "low" frequency. The select_i input selects which chain is #
-- # actually used. #
-- # #
-- # Each inverter chain is constructed as an "asynchronous" shift register. The single inverters #
-- # are connected via latches that are used to enable/disable the TRNG. Also, these latches are #
-- # used as additional delay element. By using unique enable signals for each latch, the #
-- # synthesis tool cannot "optimize" (=remove) any of the inverters out of the design making the #
-- # design platform-agnostic. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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. #
-- # ********************************************************************************************* #
-- # neoTRNG - https://github.com/stnolting/neoTRNG (c) Stephan Nolting #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
entity neoTRNG_cell is
generic (
NUM_INV_S : natural; -- number of inverters in short path
NUM_INV_L : natural -- number of inverters in long path
);
port (
clk_i : in std_ulogic; -- system clock
select_i : in std_ulogic; -- delay select
enable_i : in std_ulogic; -- enable chain input
enable_o : out std_ulogic; -- enable chain output
data_o : out std_ulogic -- sync random bit
);
end neoTRNG_cell;
architecture neoTRNG_cell_rtl of neoTRNG_cell is
signal inv_chain_s : std_ulogic_vector(NUM_INV_S-1 downto 0); -- short oscillator chain
signal inv_chain_l : std_ulogic_vector(NUM_INV_L-1 downto 0); -- long oscillator chain
signal feedback : std_ulogic; -- cell feedback/output
signal enable_sreg_s : std_ulogic_vector(NUM_INV_S-1 downto 0); -- enable shift register for short chain
signal enable_sreg_l : std_ulogic_vector(NUM_INV_L-1 downto 0); -- enable shift register for long chain
signal sync_ff : std_ulogic_vector(1 downto 0); -- output signal synchronizer
begin
-- Ring Oscillators -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Each cell provides a short inverter chain (high frequency) and a long oscillator chain (low frequency).
-- The select_i signals defines which chain is enabled.
-- NOTE: All signals that control a inverter-latch element have to be registered to ensure a single element
-- is mapped to a single LUT (or LUT + FF(latch-mode)).
-- short oscillator chain --
ring_osc_short: process(enable_i, enable_sreg_s, feedback, inv_chain_s)
begin
for i in 0 to NUM_INV_S-1 loop -- inverters in short chain
if (enable_i = '0') then -- start with a defined state (latch reset)
inv_chain_s(i) <= '0';
elsif (enable_sreg_s(i) = '1') then
if (i = NUM_INV_S-1) then -- left-most inverter?
inv_chain_s(i) <= not feedback;
else
inv_chain_s(i) <= not inv_chain_s(i+1);
end if;
end if;
end loop; -- i
end process ring_osc_short;
-- long oscillator chain --
ring_osc_long: process(enable_i, enable_sreg_l, feedback, inv_chain_l)
begin
for i in 0 to NUM_INV_L-1 loop -- inverters in long chain
if (enable_i = '0') then -- start with a defined state (latch reset)
inv_chain_l(i) <= '0';
elsif (enable_sreg_l(i) = '1') then
if (i = NUM_INV_L-1) then -- left-most inverter?
inv_chain_l(i) <= not feedback;
else
inv_chain_l(i) <= not inv_chain_l(i+1);
end if;
end if;
end loop; -- i
end process ring_osc_long;
-- length select --
feedback <= inv_chain_l(0) when (select_i = '0') else inv_chain_s(0);
-- Control --------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Using individual enable signals for each inverter from a shift register to prevent the synthesis tool
-- from removing all but one inverter (since they implement "logical identical functions" (='toggle')).
-- This makes the TRNG platform independent (since we do not need to use primitives to ensure a correct architecture).
ctrl_unit: process(clk_i)
begin
if rising_edge(clk_i) then
-- enable sreg --
enable_sreg_s <= enable_sreg_s(enable_sreg_s'left-1 downto 0) & enable_i;
enable_sreg_l <= enable_sreg_l(enable_sreg_l'left-1 downto 0) & enable_sreg_s(enable_sreg_s'left);
-- data output sync - no metastability beyond this point --
sync_ff <= sync_ff(0) & feedback;
end if;
end process ctrl_unit;
-- output for "enable chain" --
enable_o <= enable_sreg_l(enable_sreg_l'left);
-- random data output --
data_o <= sync_ff(1);
end neoTRNG_cell_rtl;

View File

@ -0,0 +1,290 @@
-- #################################################################################################
-- # << NEORV32 - Two-Wire Interface Controller (TWI) >> #
-- # ********************************************************************************************* #
-- # Supports START and STOP conditions, 8 bit data + ACK/NACK transfers and clock stretching. #
-- # Supports ACKs by the controller. No multi-controller support and no peripheral mode support #
-- # yet. Interrupt: "operation done" #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_twi is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- com lines --
twi_sda_io : inout std_logic; -- serial data line
twi_scl_io : inout std_logic; -- serial clock line
-- interrupt --
irq_o : out std_ulogic -- transfer done IRQ
);
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
constant ctrl_stop_c : natural := 2; -- -/w: Generate STOP condition
constant ctrl_prsc0_c : natural := 3; -- r/w: CLK prsc bit 0
constant ctrl_prsc1_c : natural := 4; -- r/w: CLK prsc bit 1
constant ctrl_prsc2_c : natural := 5; -- r/w: CLK prsc bit 2
constant ctrl_mack_c : natural := 6; -- r/w: generate ACK by controller for transmission
--
constant ctrl_ack_c : natural := 30; -- r/-: Set if ACK received
constant ctrl_busy_c : natural := 31; -- r/-: Set if TWI unit is busy
--
signal ctrl : std_ulogic_vector(6 downto 0); -- unit's control register
-- 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
-- twi clocking --
signal twi_clk : std_ulogic;
signal twi_phase_gen : std_ulogic_vector(3 downto 0);
signal twi_clk_phase : std_ulogic_vector(3 downto 0);
-- twi clock stretching --
signal twi_clk_halt : std_ulogic;
-- twi transceiver core --
signal arbiter : std_ulogic_vector(2 downto 0);
signal bitcnt : std_ulogic_vector(3 downto 0);
signal rtx_sreg : std_ulogic_vector(8 downto 0); -- main rx/tx shift reg
-- tri-state I/O --
signal twi_sda_in_ff : std_ulogic_vector(1 downto 0); -- SDA input sync
signal twi_scl_in_ff : std_ulogic_vector(1 downto 0); -- SCL input sync
signal twi_sda_in : std_ulogic;
signal twi_scl_in : std_ulogic;
signal twi_sda_out : std_ulogic;
signal twi_scl_out : std_ulogic;
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= rden or wren;
-- write access --
if (wren = '1') then
if (addr = twi_ctrl_addr_c) then
ctrl <= data_i(ctrl'left downto 0);
end if;
end if;
-- read access --
data_o <= (others => '0');
if (rden = '1') then
if (addr = twi_ctrl_addr_c) then
data_o(ctrl_en_c) <= ctrl(ctrl_en_c);
data_o(ctrl_prsc0_c) <= ctrl(ctrl_prsc0_c);
data_o(ctrl_prsc1_c) <= ctrl(ctrl_prsc1_c);
data_o(ctrl_prsc2_c) <= ctrl(ctrl_prsc2_c);
data_o(ctrl_mack_c) <= ctrl(ctrl_mack_c);
--
data_o(ctrl_ack_c) <= not rtx_sreg(0);
data_o(ctrl_busy_c) <= arbiter(1) or arbiter(0);
else -- twi_rtx_addr_c =>
data_o(7 downto 0) <= rtx_sreg(8 downto 1);
end if;
end if;
end if;
end process rw_access;
-- Clock Generation -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- clock generator enable --
clkgen_en_o <= ctrl(ctrl_en_c);
-- twi clock select --
twi_clk <= clkgen_i(to_integer(unsigned(ctrl(ctrl_prsc2_c downto ctrl_prsc0_c))));
-- generate four non-overlapping clock ticks at twi_clk/4 --
clock_phase_gen: process(clk_i)
begin
if rising_edge(clk_i) then
if (arbiter(2) = '0') or (arbiter(1 downto 0) = "00") then -- offline or idle
twi_phase_gen <= "0001"; -- make sure to start with a new phase, bit 0,1,2,3 stepping
elsif (twi_clk = '1') and (twi_clk_halt = '0') then -- enabled and no clock stretching detected
twi_phase_gen <= twi_phase_gen(2 downto 0) & twi_phase_gen(3); -- rotate left
end if;
end if;
end process clock_phase_gen;
-- TWI bus signals are set/sampled using 4 clock phases --
twi_clk_phase(0) <= twi_phase_gen(0) and twi_clk; -- first step
twi_clk_phase(1) <= twi_phase_gen(1) and twi_clk;
twi_clk_phase(2) <= twi_phase_gen(2) and twi_clk;
twi_clk_phase(3) <= twi_phase_gen(3) and twi_clk; -- last step
-- TWI Transceiver ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
twi_rtx_unit: process(clk_i)
begin
if rising_edge(clk_i) then
-- input synchronizer & sampler --
twi_sda_in_ff <= twi_sda_in_ff(0) & twi_sda_in;
twi_scl_in_ff <= twi_scl_in_ff(0) & twi_scl_in;
-- defaults --
irq_o <= '0';
-- serial engine --
arbiter(2) <= ctrl(ctrl_en_c); -- still activated?
case arbiter is
when "100" => -- IDLE: waiting for requests, bus might be still claimed by this controller if no STOP condition was generated
bitcnt <= (others => '0');
if (wren = '1') then
if (addr = twi_ctrl_addr_c) then
if (data_i(ctrl_start_c) = '1') then -- issue START condition
arbiter(1 downto 0) <= "01";
elsif (data_i(ctrl_stop_c) = '1') then -- issue STOP condition
arbiter(1 downto 0) <= "10";
end if;
elsif (addr = twi_rtx_addr_c) 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
rtx_sreg <= data_i(7 downto 0) & (not ctrl(ctrl_mack_c));
arbiter(1 downto 0) <= "11";
end if;
end if;
when "101" => -- START: generate START condition
if (twi_clk_phase(0) = '1') then
twi_sda_out <= '1';
elsif (twi_clk_phase(1) = '1') then
twi_sda_out <= '0';
end if;
--
if (twi_clk_phase(0) = '1') then
twi_scl_out <= '1';
elsif (twi_clk_phase(3) = '1') then
twi_scl_out <= '0';
irq_o <= '1'; -- Interrupt!
arbiter(1 downto 0) <= "00"; -- go back to IDLE
end if;
when "110" => -- STOP: generate STOP condition
if (twi_clk_phase(0) = '1') then
twi_sda_out <= '0';
elsif (twi_clk_phase(3) = '1') then
twi_sda_out <= '1';
irq_o <= '1'; -- Interrupt!
arbiter(1 downto 0) <= "00"; -- go back to IDLE
end if;
--
if (twi_clk_phase(0) = '1') then
twi_scl_out <= '0';
elsif (twi_clk_phase(1) = '1') then
twi_scl_out <= '1';
end if;
when "111" => -- TRANSMISSION: transmission in progress
if (twi_clk_phase(0) = '1') then
bitcnt <= std_ulogic_vector(unsigned(bitcnt) + 1);
twi_scl_out <= '0';
twi_sda_out <= rtx_sreg(8); -- MSB first
elsif (twi_clk_phase(1) = '1') then -- first half + second half of valid data strobe
twi_scl_out <= '1';
elsif (twi_clk_phase(3) = '1') then
rtx_sreg <= rtx_sreg(7 downto 0) & twi_sda_in_ff(twi_sda_in_ff'left); -- sample and shift left
twi_scl_out <= '0';
end if;
--
if (bitcnt = "1010") then -- 8 data bits + 1 bit for ACK + 1 tick delay
irq_o <= '1'; -- Interrupt!
arbiter(1 downto 0) <= "00"; -- go back to IDLE
end if;
when others => -- "0--" OFFLINE: TWI deactivated
twi_sda_out <= '1';
twi_scl_out <= '1';
arbiter(1 downto 0) <= "00"; -- stay here, go to idle when activated
end case;
end if;
end process twi_rtx_unit;
-- Clock Stretching Detector --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- controller wants to pull SCL high, but SCL is pulled low by peripheral --
twi_clk_halt <= '1' when (twi_scl_out = '1') and (twi_scl_in_ff(twi_scl_in_ff'left) = '0') else '0';
-- Tri-State Driver -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- SDA and SCL need to be of type std_logic to be correctly resolved in simulation
twi_sda_io <= '0' when (twi_sda_out = '0') else 'Z';
twi_scl_io <= '0' when (twi_scl_out = '0') else 'Z';
-- read-back --
twi_sda_in <= std_ulogic(twi_sda_io);
twi_scl_in <= std_ulogic(twi_scl_io);
end neorv32_twi_rtl;

View File

@ -0,0 +1,648 @@
-- #################################################################################################
-- # << NEORV32 - Universal Asynchronous Receiver and Transmitter (UART0/1) >> #
-- # ********************************************************************************************* #
-- # Frame configuration: 1 start bit, 8 bit data, parity bit (none/even/odd), 1 stop bit, #
-- # programmable BAUD rate via clock pre-scaler and 12-bit BAUD value configuration register, #
-- # optional configurable RX and TX FIFOs. #
-- # #
-- # Interrupts: Configurable RX and TX interrupt (both triggered by specific FIFO fill-levels) #
-- # #
-- # Support for RTS("RTR")/CTS hardware flow control: #
-- # * uart_rts_o = 0: RX is ready to receive a new char, enabled via CTRL.ctrl_rts_en_c #
-- # * uart_cts_i = 0: TX is allowed to send a new char, enabled via CTRL.ctrl_cts_en_c #
-- # #
-- # UART0 / UART1: #
-- # This module is used for implementing UART0 and UART1. The UART_PRIMARY generic configures the #
-- # interface register addresses and simulation outputs for UART0 (UART_PRIMARY = true) or UART1 #
-- # (UART_PRIMARY = false). #
-- # #
-- # SIMULATION MODE: #
-- # When the simulation mode is enabled (setting the ctrl.ctrl_sim_en_c bit) any write #
-- # access to the TX register will not trigger any UART activity. Instead, the written data is #
-- # output to the simulation environment. The lowest 8 bits of the written data are printed as #
-- # ASCII char to the simulator console. #
-- # This char is also stored to the file "neorv32.uartX.sim_mode.text.out" (where X = 0 for UART0 #
-- # and X = 1 for UART1). The full 32-bit write data is also stored as 8-digit hexadecimal value #
-- # to the file "neorv32.uartX.sim_mode.data.out" (where X = 0 for UART0 and X = 1 for UART1). #
-- # No interrupts are triggered when in SIMULATION MODE. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
use std.textio.all;
entity neorv32_uart is
generic (
UART_PRIMARY : boolean; -- true = primary UART (UART0), false = secondary UART (UART1)
UART_RX_FIFO : natural; -- RX fifo depth, has to be a power of two, min 1
UART_TX_FIFO : natural -- TX fifo depth, has to be a power of two, min 1
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- com lines --
uart_txd_o : out std_ulogic;
uart_rxd_i : in std_ulogic;
-- hardware flow control --
uart_rts_o : out std_ulogic; -- UART.RX ready to receive ("RTR"), low-active, optional
uart_cts_i : in std_ulogic; -- UART.TX allowed to transmit, low-active, optional
-- interrupts --
irq_rxd_o : out std_ulogic; -- uart data received interrupt
irq_txd_o : out std_ulogic -- uart transmission done interrupt
);
end neorv32_uart;
architecture neorv32_uart_rtl of neorv32_uart is
-- interface configuration for UART0 / UART1 --
constant uart_id_base_c : std_ulogic_vector(data_width_c-1 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(data_width_c-1 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(data_width_c-1 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
constant sim_data_output_en_c : boolean := true; -- dump 32-bit TX word to file when enabled
constant sim_uart_text_file_c : string := cond_sel_string_f(UART_PRIMARY, "neorv32.uart0.sim_mode.text.out", "neorv32.uart1.sim_mode.text.out");
constant sim_uart_data_file_c : string := cond_sel_string_f(UART_PRIMARY, "neorv32.uart0.sim_mode.data.out", "neorv32.uart1.sim_mode.data.out");
-- control register --
signal ctrl : std_ulogic_vector(31 downto 0);
-- control register bits --
constant ctrl_baud00_c : natural := 0; -- r/w: baud config bit 0
constant ctrl_baud01_c : natural := 1; -- r/w: baud config bit 1
constant ctrl_baud02_c : natural := 2; -- r/w: baud config bit 2
constant ctrl_baud03_c : natural := 3; -- r/w: baud config bit 3
constant ctrl_baud04_c : natural := 4; -- r/w: baud config bit 4
constant ctrl_baud05_c : natural := 5; -- r/w: baud config bit 5
constant ctrl_baud06_c : natural := 6; -- r/w: baud config bit 6
constant ctrl_baud07_c : natural := 7; -- r/w: baud config bit 7
constant ctrl_baud08_c : natural := 8; -- r/w: baud config bit 8
constant ctrl_baud09_c : natural := 9; -- r/w: baud config bit 9
constant ctrl_baud10_c : natural := 10; -- r/w: baud config bit 10
constant ctrl_baud11_c : natural := 11; -- r/w: baud config bit 11
constant ctrl_sim_en_c : natural := 12; -- r/w: UART <<SIMULATION MODE>> enable
constant ctrl_rx_empty_c : natural := 13; -- r/-: RX FIFO is empty
constant ctrl_rx_half_c : natural := 14; -- r/-: RX FIFO is at least half-full
constant ctrl_rx_full_c : natural := 15; -- r/-: RX FIFO is full
constant ctrl_tx_empty_c : natural := 16; -- r/-: TX FIFO is empty
constant ctrl_tx_half_c : natural := 17; -- r/-: TX FIFO is at least half-full
constant ctrl_tx_full_c : natural := 18; -- r/-: TX FIFO is full
-- ...
constant ctrl_rts_en_c : natural := 20; -- r/w: enable hardware flow control: assert rts_o if ready to receive
constant ctrl_cts_en_c : natural := 21; -- r/w: enable hardware flow control: send only if cts_i is asserted
constant ctrl_pmode0_c : natural := 22; -- r/w: Parity config (0=even; 1=odd)
constant ctrl_pmode1_c : natural := 23; -- r/w: Enable parity bit
constant ctrl_prsc0_c : natural := 24; -- r/w: baud prsc bit 0
constant ctrl_prsc1_c : natural := 25; -- r/w: baud prsc bit 1
constant ctrl_prsc2_c : natural := 26; -- r/w: baud prsc bit 2
constant ctrl_cts_c : natural := 27; -- r/-: current state of CTS input
constant ctrl_en_c : natural := 28; -- r/w: UART enable
constant ctrl_rx_irq_c : natural := 29; -- r/w: RX IRQ mode: 1=FIFO at least half-full; 0=FIFO not empty
constant ctrl_tx_irq_c : natural := 30; -- r/w: TX IRQ mode: 1=FIFO less than half-full; 0=FIFO not full
constant ctrl_tx_busy_c : natural := 31; -- r/-: UART transmitter is busy
-- data register flags --
constant data_lsb_c : natural := 0; -- r/-: received char LSB
constant data_msb_c : natural := 7; -- r/-: received char MSB
-- ...
constant data_rx_perr_c : natural := 28; -- r/-: RX parity error
constant data_rx_ferr_c : natural := 29; -- r/-: RX frame error
constant data_rx_overr_c : natural := 30; -- r/-: RX data overrun
constant data_rx_avail_c : natural := 31; -- r/-: RX data available
-- 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;
-- numbers of bits in transmission frame --
signal num_bits : std_ulogic_vector(3 downto 0);
-- hardware flow-control IO buffer --
signal uart_cts_ff : std_ulogic_vector(1 downto 0);
signal uart_rts : std_ulogic;
-- UART transmitter --
type tx_state_t is (S_TX_IDLE, S_TX_GET, S_TX_CHECK, S_TX_TRANSMIT, S_TX_SIM);
type tx_engine_t is record
state : tx_state_t;
busy : std_ulogic;
done : std_ulogic;
bitcnt : std_ulogic_vector(03 downto 0);
sreg : std_ulogic_vector(10 downto 0);
baud_cnt : std_ulogic_vector(11 downto 0);
cts : std_ulogic; -- allow new transmission when 1
end record;
signal tx_engine : tx_engine_t;
-- UART receiver --
type rx_state_t is (S_RX_IDLE, S_RX_RECEIVE);
type rx_engine_t is record
state : rx_state_t;
done : std_ulogic;
sync : std_ulogic_vector(04 downto 0);
bitcnt : std_ulogic_vector(03 downto 0);
sreg : std_ulogic_vector(09 downto 0);
baud_cnt : std_ulogic_vector(11 downto 0);
overr : std_ulogic;
rtr : std_ulogic; -- ready to receive when 1
end record;
signal rx_engine : rx_engine_t;
-- TX FIFO --
type tx_buffer_t is record
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
clear : std_ulogic; -- sync reset, high-active
wdata : std_ulogic_vector(31 downto 0); -- write data
rdata : std_ulogic_vector(31 downto 0); -- read data
avail : std_ulogic; -- data available?
free : std_ulogic; -- free entry available?
half : std_ulogic; -- half full
end record;
signal tx_buffer : tx_buffer_t;
-- RX FIFO --
type rx_buffer_t is record
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
clear : std_ulogic; -- sync reset, high-active
wdata : std_ulogic_vector(9 downto 0); -- write data
rdata : std_ulogic_vector(9 downto 0); -- read data
avail : std_ulogic; -- data available?
free : std_ulogic; -- free entry available?
half : std_ulogic; -- half full
end record;
signal rx_buffer : rx_buffer_t;
-- interrupt generator --
type irq_t is record
set : std_ulogic;
buf : std_ulogic_vector(1 downto 0);
end record;
signal rx_irq, tx_irq : irq_t;
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (is_power_of_two_f(UART_RX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: UART" &
cond_sel_string_f(UART_PRIMARY, "0", "1") & " <UART_RX_FIFO> has to be a power of two." severity error;
assert not (is_power_of_two_f(UART_TX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: UART" &
cond_sel_string_f(UART_PRIMARY, "0", "1") & " <UART_TX_FIFO> has to be a power of two." severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- bus access acknowledge --
ack_o <= wren or rden;
-- write access --
if (wren = '1') then
if (addr = uart_id_ctrl_addr_c) then
ctrl <= (others => '0');
ctrl(ctrl_baud11_c downto ctrl_baud00_c) <= data_i(ctrl_baud11_c downto ctrl_baud00_c);
ctrl(ctrl_sim_en_c) <= data_i(ctrl_sim_en_c);
ctrl(ctrl_pmode1_c downto ctrl_pmode0_c) <= data_i(ctrl_pmode1_c downto ctrl_pmode0_c);
ctrl(ctrl_prsc2_c downto ctrl_prsc0_c) <= data_i(ctrl_prsc2_c downto ctrl_prsc0_c);
ctrl(ctrl_rts_en_c) <= data_i(ctrl_rts_en_c);
ctrl(ctrl_cts_en_c) <= data_i(ctrl_cts_en_c);
ctrl(ctrl_rx_irq_c) <= data_i(ctrl_rx_irq_c);
ctrl(ctrl_tx_irq_c) <= data_i(ctrl_tx_irq_c);
ctrl(ctrl_en_c) <= data_i(ctrl_en_c);
end if;
end if;
-- read access --
data_o <= (others => '0');
if (rden = '1') then
if (addr = uart_id_ctrl_addr_c) then
data_o(ctrl_baud11_c downto ctrl_baud00_c) <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
data_o(ctrl_sim_en_c) <= ctrl(ctrl_sim_en_c);
data_o(ctrl_pmode1_c downto ctrl_pmode0_c) <= ctrl(ctrl_pmode1_c downto ctrl_pmode0_c);
data_o(ctrl_prsc2_c downto ctrl_prsc0_c) <= ctrl(ctrl_prsc2_c downto ctrl_prsc0_c);
data_o(ctrl_rts_en_c) <= ctrl(ctrl_rts_en_c);
data_o(ctrl_cts_en_c) <= ctrl(ctrl_cts_en_c);
data_o(ctrl_rx_empty_c) <= not rx_buffer.avail;
data_o(ctrl_rx_half_c) <= rx_buffer.half;
data_o(ctrl_rx_full_c) <= not rx_buffer.free;
data_o(ctrl_tx_empty_c) <= not tx_buffer.avail;
data_o(ctrl_tx_half_c) <= tx_buffer.half;
data_o(ctrl_tx_full_c) <= not tx_buffer.free;
data_o(ctrl_en_c) <= ctrl(ctrl_en_c);
data_o(ctrl_rx_irq_c) <= ctrl(ctrl_rx_irq_c) and bool_to_ulogic_f(boolean(UART_RX_FIFO > 1)); -- tie to zero if UART_RX_FIFO = 1
data_o(ctrl_tx_irq_c) <= ctrl(ctrl_tx_irq_c) and bool_to_ulogic_f(boolean(UART_TX_FIFO > 1)); -- tie to zero if UART_TX_FIFO = 1
data_o(ctrl_tx_busy_c) <= tx_engine.busy;
data_o(ctrl_cts_c) <= uart_cts_ff(1);
else -- uart_id_rtx_addr_c
data_o(data_msb_c downto data_lsb_c) <= rx_buffer.rdata(7 downto 0);
data_o(data_rx_perr_c) <= rx_buffer.rdata(8);
data_o(data_rx_ferr_c) <= rx_buffer.rdata(9);
data_o(data_rx_overr_c) <= rx_engine.overr;
data_o(data_rx_avail_c) <= rx_buffer.avail; -- data available (valid?)
end if;
end if;
end if;
end process rw_access;
-- number of bits to be sampled --
-- if parity flag is ENABLED: 11 bit -> "1011" (1 start bit + 8 data bits + 1 parity bit + 1 stop bit)
-- if parity flag is DISABLED: 10 bit -> "1010" (1 start bit + 8 data bits + 1 stop bit)
num_bits <= "1011" when (ctrl(ctrl_pmode1_c) = '1') else "1010";
-- Clock Selection ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- clock enable --
clkgen_en_o <= ctrl(ctrl_en_c);
-- uart clock select --
uart_clk <= clkgen_i(to_integer(unsigned(ctrl(ctrl_prsc2_c downto ctrl_prsc0_c))));
-- TX FIFO --------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
tx_engine_fifo_inst: neorv32_fifo
generic map (
FIFO_DEPTH => UART_TX_FIFO, -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH => 32, -- size of data elements in fifo (32-bit only for simulation)
FIFO_RSYNC => false, -- async read
FIFO_SAFE => true -- safe access
)
port map (
-- control --
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => tx_buffer.clear, -- sync reset, high-active
level_o => open,
half_o => tx_buffer.half, -- FIFO at least half-full
-- write port --
wdata_i => tx_buffer.wdata, -- write data
we_i => tx_buffer.we, -- write enable
free_o => tx_buffer.free, -- at least one entry is free when set
-- read port --
re_i => tx_buffer.re, -- read enable
rdata_o => tx_buffer.rdata, -- read data
avail_o => tx_buffer.avail -- data available when set
);
-- control --
tx_buffer.clear <= not ctrl(ctrl_en_c);
-- write access --
tx_buffer.we <= '1' when (wren = '1') and (addr = uart_id_rtx_addr_c) else '0';
tx_buffer.wdata <= data_i;
-- UART Transmitter Engine ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
uart_tx_engine: process(clk_i)
begin
if rising_edge(clk_i) then
-- defaults --
uart_txd_o <= '1'; -- keep TX line idle (=high) if waiting for permission to start sending (->CTS)
tx_buffer.re <= '0';
tx_engine.done <= '0';
-- FSM --
if (ctrl(ctrl_en_c) = '0') then -- disabled
tx_engine.state <= S_TX_IDLE;
else
case tx_engine.state is
when S_TX_IDLE => -- wait for new data to send
-- ------------------------------------------------------------
if (tx_buffer.avail = '1') then -- new data available
if (ctrl(ctrl_sim_en_c) = '0') then -- normal mode
tx_engine.state <= S_TX_GET;
else -- simulation mode
tx_engine.state <= S_TX_SIM;
end if;
tx_buffer.re <= '1';
end if;
when S_TX_GET => -- get new data from buffer and prepare transmission
-- ------------------------------------------------------------
tx_engine.baud_cnt <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
tx_engine.bitcnt <= num_bits;
if (ctrl(ctrl_pmode1_c) = '1') then -- add parity flag
-- stop bit & parity bit & data (8-bit) & start bit
tx_engine.sreg <= '1' & (xor_reduce_f(tx_buffer.rdata(7 downto 0)) xor ctrl(ctrl_pmode0_c)) & tx_buffer.rdata(7 downto 0) & '0';
else
-- (dummy fill-bit &) stop bit & data (8-bit) & start bit
tx_engine.sreg <= '1' & '1' & tx_buffer.rdata(7 downto 0) & '0';
end if;
tx_engine.state <= S_TX_CHECK;
when S_TX_CHECK => -- check if allowed to send
-- ------------------------------------------------------------
if (tx_engine.cts = '1') then -- clear to send
tx_engine.state <= S_TX_TRANSMIT;
end if;
when S_TX_TRANSMIT => -- transmit data
-- ------------------------------------------------------------
if (uart_clk = '1') then
if (or_reduce_f(tx_engine.baud_cnt) = '0') then -- bit done?
tx_engine.baud_cnt <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
tx_engine.bitcnt <= std_ulogic_vector(unsigned(tx_engine.bitcnt) - 1);
tx_engine.sreg <= '1' & tx_engine.sreg(tx_engine.sreg'left downto 1);
else
tx_engine.baud_cnt <= std_ulogic_vector(unsigned(tx_engine.baud_cnt) - 1);
end if;
end if;
uart_txd_o <= tx_engine.sreg(0);
if (or_reduce_f(tx_engine.bitcnt) = '0') then -- all bits send?
tx_engine.done <= '1'; -- sending done
tx_engine.state <= S_TX_IDLE;
end if;
when S_TX_SIM => -- simulation mode output
-- ------------------------------------------------------------
tx_engine.state <= S_TX_IDLE;
when others => -- undefined
-- ------------------------------------------------------------
tx_engine.state <= S_TX_IDLE;
end case;
end if;
end if;
end process uart_tx_engine;
-- transmitter busy --
tx_engine.busy <= '0' when (tx_engine.state = S_TX_IDLE) else '1';
-- UART Receiver Engine -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
uart_rx_engine: process(clk_i)
begin
if rising_edge(clk_i) then
-- input synchronizer --
rx_engine.sync <= uart_rxd_i & rx_engine.sync(rx_engine.sync'left downto 1);
-- default --
rx_engine.done <= '0';
-- FSM --
if (ctrl(ctrl_en_c) = '0') then -- disabled
rx_engine.overr <= '0';
rx_engine.state <= S_RX_IDLE;
else
case rx_engine.state is
when S_RX_IDLE => -- idle; prepare receive
-- ------------------------------------------------------------
rx_engine.baud_cnt <= '0' & ctrl(ctrl_baud11_c downto ctrl_baud01_c); -- half baud delay at the beginning to sample in the middle of each bit
rx_engine.bitcnt <= num_bits;
if (rx_engine.sync(3 downto 0) = "0011") then -- start bit? (falling edge)
rx_engine.state <= S_RX_RECEIVE;
end if;
when S_RX_RECEIVE => -- receive data
-- ------------------------------------------------------------
if (uart_clk = '1') then
if (or_reduce_f(rx_engine.baud_cnt) = '0') then -- bit done
rx_engine.baud_cnt <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
rx_engine.bitcnt <= std_ulogic_vector(unsigned(rx_engine.bitcnt) - 1);
rx_engine.sreg <= rx_engine.sync(2) & rx_engine.sreg(rx_engine.sreg'left downto 1);
else
rx_engine.baud_cnt <= std_ulogic_vector(unsigned(rx_engine.baud_cnt) - 1);
end if;
end if;
if (or_reduce_f(rx_engine.bitcnt) = '0') then -- all bits received?
rx_engine.done <= '1'; -- receiving done
rx_engine.state <= S_RX_IDLE;
end if;
when others => -- undefined
-- ------------------------------------------------------------
rx_engine.state <= S_RX_IDLE;
end case;
-- overrun flag --
if (rden = '1') and (addr = uart_id_rtx_addr_c) then -- clear when reading data register
rx_engine.overr <= '0';
elsif (rx_buffer.we = '1') and (rx_buffer.free = '0') then -- write to full FIFO
rx_engine.overr <= '1';
end if;
end if;
end if;
end process uart_rx_engine;
-- RX engine ready for a new char? --
rx_engine.rtr <= '1' when (rx_engine.state = S_RX_IDLE) and (ctrl(ctrl_en_c) = '1') else '0';
-- RX FIFO --------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rx_engine_fifo_inst: neorv32_fifo
generic map (
FIFO_DEPTH => UART_RX_FIFO, -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH => 10, -- size of data elements in fifo
FIFO_RSYNC => false, -- async read
FIFO_SAFE => true -- safe access
)
port map (
-- control --
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => rx_buffer.clear, -- sync reset, high-active
level_o => open,
half_o => rx_buffer.half, -- FIFO at least half-full
-- write port --
wdata_i => rx_buffer.wdata, -- write data
we_i => rx_buffer.we, -- write enable
free_o => rx_buffer.free, -- at least one entry is free when set
-- read port --
re_i => rx_buffer.re, -- read enable
rdata_o => rx_buffer.rdata, -- read data
avail_o => rx_buffer.avail -- data available when set
);
-- control --
rx_buffer.clear <= not ctrl(ctrl_en_c);
-- read/write access --
rx_buffer.wdata(7 downto 0) <= rx_engine.sreg(7 downto 0) when (ctrl(ctrl_pmode1_c) = '1') else rx_engine.sreg(8 downto 1); -- RX data
rx_buffer.wdata(8) <= ctrl(ctrl_pmode1_c) and (xor_reduce_f(rx_engine.sreg(8 downto 0)) xor ctrl(ctrl_pmode0_c)); -- parity error flag
rx_buffer.wdata(9) <= not rx_engine.sreg(9); -- frame error flag: check stop bit (error if not set)
rx_buffer.we <= '1' when (rx_engine.bitcnt = "0000") and (rx_engine.state = S_RX_RECEIVE) else '0'; -- RX complete
rx_buffer.re <= '1' when (rden = '1') and (addr = uart_id_rtx_addr_c) else '0';
-- Hardware Flow Control ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
tx_engine.cts <= (not uart_cts_ff(1)) when (ctrl(ctrl_cts_en_c) = '1') else '1'; -- input is low-active, internal signal is high-active
uart_rts <= (not rx_engine.rtr) when (ctrl(ctrl_rts_en_c) = '1') else '0'; -- output is low-active
-- flow-control input/output synchronizer --
flow_control_buffer: process(clk_i)
begin
if rising_edge(clk_i) then -- should be mapped to IOBs
uart_cts_ff <= uart_cts_ff(0) & uart_cts_i;
uart_rts_o <= uart_rts;
end if;
end process flow_control_buffer;
-- Interrupt Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
irq_type: process(ctrl, tx_buffer, rx_buffer, tx_engine.done)
begin
-- TX interrupt --
if (UART_TX_FIFO = 1) or (ctrl(ctrl_tx_irq_c) = '0') then
tx_irq.set <= tx_buffer.free and tx_engine.done; -- fire IRQ if FIFO is not full
else
tx_irq.set <= (not tx_buffer.half) and tx_engine.done; -- fire IRQ if FIFO is less than half-full
end if;
-- RX interrupt --
if (UART_RX_FIFO = 1) or (ctrl(ctrl_rx_irq_c) = '0') then
rx_irq.set <= rx_buffer.avail; -- fire IRQ if FIFO is not empty
else
rx_irq.set <= rx_buffer.half; -- fire IRQ if FIFO is at least half-full
end if;
end process irq_type;
-- interrupt edge detector --
irq_detect: process(clk_i)
begin
if rising_edge(clk_i) then
if (ctrl(ctrl_en_c) = '0') then
tx_irq.buf <= "00";
rx_irq.buf <= "00";
else
tx_irq.buf <= tx_irq.buf(0) & tx_irq.set;
rx_irq.buf <= rx_irq.buf(0) & rx_irq.set;
end if;
end if;
end process irq_detect;
-- IRQ requests to CPU --
irq_txd_o <= '1' when (tx_irq.buf = "01") else '0';
irq_rxd_o <= '1' when (rx_irq.buf = "01") else '0';
-- SIMULATION Transmitter -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- pragma translate_off
-- synthesis translate_off
-- RTL_SYNTHESIS OFF
sim_output: process(clk_i) -- for SIMULATION ONLY!
file file_uart_text_out : text open write_mode is sim_uart_text_file_c;
file file_uart_data_out : text open write_mode is sim_uart_data_file_c;
variable char_v : integer;
variable line_screen_v : line; -- we need several line variables here since "writeline" seems to flush the source variable
variable line_text_v : line;
variable line_data_v : line;
begin
if rising_edge(clk_i) then
if (tx_engine.state = S_TX_SIM) then -- UART simulation mode
-- print lowest byte as ASCII char --
char_v := to_integer(unsigned(tx_buffer.rdata(7 downto 0)));
if (char_v >= 128) then -- out of range?
char_v := 0;
end if;
if (char_v /= 10) and (char_v /= 13) then -- skip line breaks - they are issued via "writeline"
if (sim_screen_output_en_c = true) then
write(line_screen_v, character'val(char_v));
end if;
if (sim_text_output_en_c = true) then
write(line_text_v, character'val(char_v));
end if;
end if;
if (char_v = 10) then -- line break: write to screen and text file
if (sim_screen_output_en_c = true) then
writeline(output, line_screen_v);
end if;
if (sim_text_output_en_c = true) then
writeline(file_uart_text_out, line_text_v);
end if;
end if;
-- dump raw data as 8 hex chars to file --
if (sim_data_output_en_c = true) then
for x in 7 downto 0 loop
write(line_data_v, to_hexchar_f(tx_buffer.rdata(3+x*4 downto 0+x*4))); -- write in hex form
end loop; -- x
writeline(file_uart_data_out, line_data_v);
end if;
end if;
end if;
end process sim_output;
-- RTL_SYNTHESIS ON
-- synthesis translate_on
-- pragma translate_on
end neorv32_uart_rtl;

View File

@ -0,0 +1,244 @@
-- #################################################################################################
-- # << NEORV32 - Watch Dog Timer (WDT) >> #
-- # ********************************************************************************************* #
-- # Watchdog counter to trigger an action if the CPU gets stuck. #
-- # The internal counter is 20-bit wide. If this counter overflows one of two possible actions is #
-- # triggered: Generate an IRQ or force a hardware reset of the system. #
-- # A WDT action can also be triggered manually at any time by setting the FORCE bit. #
-- # #
-- # Access to the control register can be permanently locked by setting the lock bit. This bit #
-- # can only be cleared by a hardware reset (external or caused by the watchdog itself). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_wdt is
generic (
DEBUG_EN : boolean -- CPU debug mode implemented?
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
rstn_i : in std_ulogic; -- global reset line, low-active
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- CPU in debug mode? --
cpu_debug_i : in std_ulogic;
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0);
-- timeout event --
irq_o : out std_ulogic; -- timeout IRQ
rstn_o : out std_ulogic -- timeout reset, low_active, use as async
);
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_clksel0_c : natural := 1; -- r/w: prescaler select bit 0
constant ctrl_clksel1_c : natural := 2; -- r/w: prescaler select bit 1
constant ctrl_clksel2_c : natural := 3; -- r/w: prescaler select bit 2
constant ctrl_mode_c : natural := 4; -- r/w: 0: WDT timeout triggers interrupt, 1: WDT timeout triggers hard reset
constant ctrl_rcause_c : natural := 5; -- r/-: cause of last action (reset/IRQ): 0=external reset, 1=watchdog overflow
constant ctrl_reset_c : natural := 6; -- -/w: reset WDT if set
constant ctrl_force_c : natural := 7; -- -/w: force WDT action
constant ctrl_lock_c : natural := 8; -- r/w: lock access to control register when set
constant ctrl_dben_c : natural := 9; -- r/w: allow WDT to continue operation even when in debug mode
constant ctrl_half_c : natural := 10; -- r/-: set if at least half of the max. timeout counter value has been reached
-- 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; -- 1=WDT enabled
clk_sel : std_ulogic_vector(2 downto 0);
mode : std_ulogic; -- 0=trigger IRQ on overflow; 1=trigger hard reset on overflow
rcause : std_ulogic; -- cause of last system reset: '0' = external, '1' = watchdog
reset : std_ulogic; -- reset WDT
enforce : std_ulogic; -- force action
lock : std_ulogic; -- lock control register
dben : std_ulogic; -- allow operation also in debug mode
end record;
signal ctrl : ctrl_t;
-- prescaler clock generator --
signal prsc_tick : std_ulogic;
-- WDT core --
signal wdt_cnt : std_ulogic_vector(20 downto 0);
signal hw_rst : std_ulogic;
signal rst_gen : std_ulogic_vector(03 downto 0);
signal cnt_en : std_ulogic;
-- internal reset (sync, low-active) --
signal rstn_sync : std_ulogic;
begin
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = wdt_base_c(hi_abb_c downto lo_abb_c)) else '0';
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Write Access ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
write_access: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
ctrl.reset <= '1'; -- reset counter on start-up
ctrl.enforce <= '0';
ctrl.enable <= '0'; -- disable WDT
ctrl.mode <= '0';
ctrl.clk_sel <= (others => '0');
ctrl.lock <= '0';
ctrl.dben <= '0';
elsif rising_edge(clk_i) then
if (rstn_sync = '0') then -- internal reset
ctrl.reset <= '1'; -- reset counter on start-up
ctrl.enforce <= '0';
ctrl.enable <= '0'; -- disable WDT
ctrl.mode <= '0';
ctrl.clk_sel <= (others => '0');
ctrl.lock <= '0';
ctrl.dben <= '0';
else
-- auto-clear WDT reset and WDT force flags --
ctrl.reset <= '0';
ctrl.enforce <= '0';
-- actual write access --
if (wren = '1') then
ctrl.reset <= data_i(ctrl_reset_c);
ctrl.enforce <= data_i(ctrl_force_c);
if (ctrl.lock = '0') then -- update configuration only if not locked
ctrl.enable <= data_i(ctrl_enable_c);
ctrl.mode <= data_i(ctrl_mode_c);
ctrl.clk_sel <= data_i(ctrl_clksel2_c downto ctrl_clksel0_c);
ctrl.lock <= data_i(ctrl_lock_c);
ctrl.dben <= data_i(ctrl_dben_c) and bool_to_ulogic_f(DEBUG_EN);
end if;
end if;
end if;
end if;
end process write_access;
-- clock generator --
clkgen_en_o <= ctrl.enable; -- enable clock generator
prsc_tick <= clkgen_i(to_integer(unsigned(ctrl.clk_sel))); -- clock enable tick
-- Watchdog Counter -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
wdt_counter: process(clk_i)
begin
if rising_edge(clk_i) then
if (ctrl.reset = '1') then -- watchdog reset
wdt_cnt <= (others => '0');
elsif (cnt_en = '1') then
wdt_cnt <= std_ulogic_vector(unsigned('0' & wdt_cnt(wdt_cnt'left-1 downto 0)) + 1);
end if;
end if;
end process wdt_counter;
-- WDT counter enable --
cnt_en <= ctrl.enable and prsc_tick and ((not cpu_debug_i) or ctrl.dben);
-- action trigger --
irq_o <= ctrl.enable and (wdt_cnt(wdt_cnt'left) or ctrl.enforce) and (not ctrl.mode); -- mode 0: IRQ
hw_rst <= ctrl.enable and (wdt_cnt(wdt_cnt'left) or ctrl.enforce) and ( ctrl.mode); -- mode 1: RESET
-- Reset Generator & Action Cause Indicator -----------------------------------------------
-- -------------------------------------------------------------------------------------------
reset_generator: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
ctrl.rcause <= '0';
rst_gen <= (others => '1'); -- do NOT fire on reset!
rstn_sync <= '1';
elsif rising_edge(clk_i) then
ctrl.rcause <= ctrl.rcause or hw_rst; -- sticky-set on WDT timeout/force
if (hw_rst = '1') then
rst_gen <= (others => '0');
else
rst_gen <= rst_gen(rst_gen'left-1 downto 0) & '1';
end if;
rstn_sync <= rst_gen(rst_gen'left);
end if;
end process reset_generator;
-- system reset --
rstn_o <= rst_gen(rst_gen'left);
-- Read Access ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
read_access: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= rden or wren;
if (rden = '1') then
data_o(ctrl_enable_c) <= ctrl.enable;
data_o(ctrl_mode_c) <= ctrl.mode;
data_o(ctrl_rcause_c) <= ctrl.rcause;
data_o(ctrl_clksel2_c downto ctrl_clksel0_c) <= ctrl.clk_sel;
data_o(ctrl_lock_c) <= ctrl.lock;
data_o(ctrl_dben_c) <= ctrl.dben;
data_o(ctrl_half_c) <= wdt_cnt(wdt_cnt'left-1);
else
data_o <= (others => '0');
end if;
end if;
end process read_access;
end neorv32_wdt_rtl;

View File

@ -0,0 +1,274 @@
-- #################################################################################################
-- # << NEORV32 - External Bus Interface (WISHBONE) >> #
-- # ********************************************************************************************* #
-- # All bus accesses from the CPU, which do not target the internal IO region / the internal #
-- # bootloader / the internal instruction or data memories (if implemented), are delegated via #
-- # this Wishbone gateway to the external bus interface. Accessed peripherals can have a response #
-- # latency of up to BUS_TIMEOUT - 1 cycles. #
-- # #
-- # Even when all processor-internal memories and IO devices are disabled, the EXTERNAL address #
-- # space ENDS at address 0xffff0000 (begin of internal BOOTROM address space). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_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
);
port (
-- global control --
clk_i : in std_ulogic; -- global clock line
rstn_i : in std_ulogic; -- global reset line, low-active
-- host access --
src_i : in std_ulogic; -- access type (0: data, 1:instruction)
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
ben_i : in std_ulogic_vector(03 downto 0); -- byte write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
lock_i : in std_ulogic; -- exclusive access request
ack_o : out std_ulogic; -- transfer acknowledge
err_o : out std_ulogic; -- transfer error
tmo_o : out std_ulogic; -- transfer timeout
priv_i : in std_ulogic_vector(01 downto 0); -- current CPU privilege level
ext_o : out std_ulogic; -- active external access
-- wishbone interface --
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_lock_o : out std_ulogic; -- exclusive access request
wb_ack_i : in std_ulogic; -- transfer acknowledge
wb_err_i : in std_ulogic -- transfer error
);
end neorv32_wishbone;
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_boot_acc : std_ulogic;
signal xbus_access : std_ulogic;
-- bus arbiter
type ctrl_state_t is (IDLE, BUSY);
type ctrl_t is record
state : ctrl_state_t;
state_ff : ctrl_state_t;
we : std_ulogic;
adr : std_ulogic_vector(31 downto 0);
wdat : std_ulogic_vector(31 downto 0);
rdat : std_ulogic_vector(31 downto 0);
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;
lock : std_ulogic;
priv : std_ulogic_vector(01 downto 0);
end record;
signal ctrl : ctrl_t;
signal stb_int : std_ulogic;
signal cyc_int : std_ulogic;
signal rdata : std_ulogic_vector(31 downto 0);
-- async RX mode --
signal ack_gated : std_ulogic;
signal rdata_gated : std_ulogic_vector(31 downto 0);
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- protocol --
assert not (PIPE_MODE = false) report "NEORV32 PROCESSOR CONFIG NOTE: External Bus Interface - Implementing STANDARD Wishbone protocol." severity note;
assert not (PIPE_MODE = true) report "NEORV32 PROCESSOR CONFIG NOTE: External Bus Interface - Implementing PIEPLINED Wishbone protocol." severity note;
-- bus timeout --
assert not (BUS_TIMEOUT /= 0) report "NEORV32 PROCESSOR CONFIG NOTE: External Bus Interface - Implementing auto-timeout (" & integer'image(BUS_TIMEOUT) & " cycles)." severity note;
assert not (BUS_TIMEOUT = 0) report "NEORV32 PROCESSOR CONFIG WARNING: External Bus Interface - Implementing NO auto-timeout (can cause permanent CPU stall!)." severity warning;
-- endianness --
assert not (BIG_ENDIAN = false) report "NEORV32 PROCESSOR CONFIG NOTE: External Bus Interface - Implementing LITTLE-endian byte order." severity note;
assert not (BIG_ENDIAN = true) report "NEORV32 PROCESSOR CONFIG NOTE: External Bus Interface - Implementing BIG-endian byte." severity note;
-- async RX --
assert not (ASYNC_RX = false) report "NEORV32 PROCESSOR CONFIG NOTE: External Bus Interface - Implementing registered RX path." severity note;
assert not (ASYNC_RX = true) report "NEORV32 PROCESSOR CONFIG NOTE: External Bus Interface - Implementing ASYNC RX path." severity note;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- access to processor-internal IMEM or DMEM? --
int_imem_acc <= '1' when (addr_i(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 (addr_i(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 devices? --
int_boot_acc <= '1' when (addr_i(31 downto 16) = boot_rom_base_c(31 downto 16)) else '0'; -- hacky!
-- actual external bus access? --
xbus_access <= (not int_imem_acc) and (not int_dmem_acc) and (not int_boot_acc);
-- Bus Arbiter -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
bus_arbiter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
ctrl.state <= IDLE;
ctrl.state_ff <= IDLE;
ctrl.we <= def_rst_val_c;
ctrl.adr <= (others => def_rst_val_c);
ctrl.wdat <= (others => def_rst_val_c);
ctrl.rdat <= (others => def_rst_val_c);
ctrl.sel <= (others => def_rst_val_c);
ctrl.timeout <= (others => def_rst_val_c);
ctrl.ack <= def_rst_val_c;
ctrl.err <= def_rst_val_c;
ctrl.tmo <= def_rst_val_c;
ctrl.src <= def_rst_val_c;
ctrl.lock <= def_rst_val_c;
ctrl.priv <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
-- defaults --
ctrl.state_ff <= ctrl.state;
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 --
case ctrl.state is
when IDLE => -- waiting for host request
-- ------------------------------------------------------------
-- buffer all outgoing signals --
ctrl.we <= wren_i;
ctrl.adr <= addr_i;
if (BIG_ENDIAN = true) then -- big-endian
ctrl.wdat <= bswap32_f(data_i);
ctrl.sel <= bit_rev_f(ben_i);
else -- little-endian
ctrl.wdat <= data_i;
ctrl.sel <= ben_i;
end if;
ctrl.src <= src_i;
ctrl.lock <= lock_i;
ctrl.priv <= priv_i;
-- valid new or buffered read/write request --
if ((xbus_access and (wren_i or rden_i)) = '1') then
ctrl.state <= BUSY;
end if;
when BUSY => -- transfer in progress
-- ------------------------------------------------------------
ctrl.rdat <= wb_dat_i;
if (wb_err_i = '1') then -- abnormal bus termination
ctrl.err <= '1';
ctrl.state <= IDLE;
elsif (timeout_en_c = true) and (or_reduce_f(ctrl.timeout) = '0') then -- enabled timeout
ctrl.tmo <= '1';
ctrl.state <= IDLE;
elsif (wb_ack_i = '1') then -- normal bus termination
ctrl.ack <= '1';
ctrl.state <= IDLE;
end if;
-- timeout counter --
if (timeout_en_c = true) then
ctrl.timeout <= std_ulogic_vector(unsigned(ctrl.timeout) - 1); -- timeout counter
end if;
when others => -- undefined
-- ------------------------------------------------------------
ctrl.state <= IDLE;
end case;
end if;
end process bus_arbiter;
-- host access --
ack_gated <= wb_ack_i when (ctrl.state = BUSY) else '0'; -- CPU ack gate for "async" RX
rdata_gated <= wb_dat_i when (ctrl.state = BUSY) else (others => '0'); -- CPU read data gate for "async" RX
rdata <= ctrl.rdat when (ASYNC_RX = false) else rdata_gated;
ext_o <= '1' when (ctrl.state = BUSY) else '0'; -- active external access
data_o <= rdata when (BIG_ENDIAN = false) else bswap32_f(rdata); -- endianness conversion
ack_o <= ctrl.ack when (ASYNC_RX = false) else ack_gated;
err_o <= ctrl.err;
tmo_o <= ctrl.tmo;
-- wishbone interface --
wb_tag_o(0) <= '0' when (ctrl.priv = priv_mode_u_c) else '1'; -- unprivileged access when in user mode
wb_tag_o(1) <= '0'; -- 0 = secure, 1 = non-secure
wb_tag_o(2) <= ctrl.src; -- 0 = data access, 1 = instruction access
wb_lock_o <= ctrl.lock; -- 1 = exclusive access request
wb_adr_o <= ctrl.adr;
wb_dat_o <= ctrl.wdat;
wb_we_o <= ctrl.we;
wb_sel_o <= ctrl.sel;
wb_stb_o <= stb_int when (PIPE_MODE = true) else cyc_int;
wb_cyc_o <= cyc_int;
stb_int <= '1' when (ctrl.state = BUSY) and (ctrl.state_ff /= BUSY) else '0';
cyc_int <= '1' when (ctrl.state = BUSY) else '0';
end neorv32_wishbone_rtl;

View File

@ -0,0 +1,229 @@
-- #################################################################################################
-- # << NEORV32 - External Interrupt Controller (XIRQ) >> #
-- # ********************************************************************************************* #
-- # Simple interrupt controller for platform (processor-external) interrupts. Up to 32 channels #
-- # are supported that get (optionally) prioritized into a single CPU interrupt. #
-- # #
-- # The actual trigger configuration has to be done BEFORE synthesis using the XIRQ_TRIGGER_TYPE #
-- # and XIRQ_TRIGGER_POLARITY generics. These allow to configure channel-independent low-level, #
-- # high-level, falling-edge and rising-edge triggers. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_xirq is
generic (
XIRQ_NUM_CH : natural; -- number of external IRQ channels (0..32)
XIRQ_TRIGGER_TYPE : std_ulogic_vector(31 downto 0); -- trigger type: 0=level, 1=edge
XIRQ_TRIGGER_POLARITY : std_ulogic_vector(31 downto 0) -- trigger polarity: 0=low-level/falling-edge, 1=high-level/rising-edge
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- external interrupt lines --
xirq_i : in std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
-- CPU interrupt --
cpu_irq_o : out std_ulogic
);
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
-- control registers --
signal irq_enable : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0); -- r/w: interrupt enable
signal clr_pending : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0); -- r/w: clear pending IRQs
signal irq_src : std_ulogic_vector(4 downto 0); -- r/w: source IRQ, ACK on any write
-- interrupt trigger --
signal irq_sync : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
signal irq_sync2 : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
signal irq_trig : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
-- interrupt buffer --
signal irq_buf : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
signal irq_fire : std_ulogic;
-- interrupt source --
signal irq_src_nxt : std_ulogic_vector(4 downto 0);
-- arbiter --
signal irq_run : std_ulogic;
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not ((XIRQ_NUM_CH < 0) or (XIRQ_NUM_CH > 32)) report "NEORV32 PROCESSOR CONFIG ERROR: Number of XIRQ inputs <XIRQ_NUM_CH> has to be 0..32." severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(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) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- bus handshake --
ack_o <= rden or wren;
-- write access --
clr_pending <= (others => '1');
if (wren = '1') then
-- channel-enable --
if (addr = xirq_enable_addr_c) then
irq_enable <= data_i(XIRQ_NUM_CH-1 downto 0);
end if;
-- clear pending IRQs --
if (addr = xirq_pending_addr_c) then
clr_pending <= data_i(XIRQ_NUM_CH-1 downto 0); -- set zero to clear pending IRQ
end if;
end if;
-- read access --
data_o <= (others => '0');
if (rden = '1') then
case addr is
when xirq_enable_addr_c => data_o(XIRQ_NUM_CH-1 downto 0) <= irq_enable; -- channel-enable
when xirq_pending_addr_c => data_o(XIRQ_NUM_CH-1 downto 0) <= irq_buf; -- pending IRQs
when xirq_source_addr_c => data_o(4 downto 0) <= irq_src; -- source IRQ
when others => NULL;
end case;
end if;
end if;
end process rw_access;
-- IRQ Trigger --------------------------------------------------------------
-- -----------------------------------------------------------------------------
irq_trigger: process(clk_i)
begin
if rising_edge(clk_i) then
irq_sync <= xirq_i;
irq_sync2 <= irq_sync;
end if;
end process irq_trigger;
irq_trigger_comb: process(irq_sync, irq_sync2)
variable sel_v : std_ulogic_vector(1 downto 0);
begin
for i in 0 to XIRQ_NUM_CH-1 loop
sel_v := XIRQ_TRIGGER_TYPE(i) & XIRQ_TRIGGER_POLARITY(i);
case sel_v is
when "00" => irq_trig(i) <= not irq_sync(i); -- low-level
when "01" => irq_trig(i) <= irq_sync(i); -- high-level
when "10" => irq_trig(i) <= (not irq_sync(i)) and irq_sync2(i); -- falling-edge
when "11" => irq_trig(i) <= irq_sync(i) and (not irq_sync2(i)); -- rising-edge
when others => irq_trig(i) <= '0';
end case;
end loop;
end process irq_trigger_comb;
-- IRQ Buffer ---------------------------------------------------------------
-- -----------------------------------------------------------------------------
irq_buffer: process(clk_i)
begin
if rising_edge(clk_i) then
irq_buf <= (irq_buf or (irq_trig and irq_enable)) and clr_pending;
end if;
end process irq_buffer;
-- anyone firing? --
irq_fire <= or_reduce_f(irq_buf);
-- IRQ Priority Encoder -----------------------------------------------------
-- -----------------------------------------------------------------------------
irq_priority: process(irq_buf)
begin
irq_src_nxt <= (others => '0');
if (XIRQ_NUM_CH > 1) then
for i in 0 to XIRQ_NUM_CH-1 loop
if (irq_buf(i) = '1') then
irq_src_nxt(index_size_f(XIRQ_NUM_CH)-1 downto 0) <= std_ulogic_vector(to_unsigned(i, index_size_f(XIRQ_NUM_CH)));
exit;
end if;
end loop;
end if;
end process irq_priority;
-- IRQ Arbiter --------------------------------------------------------------
-- -----------------------------------------------------------------------------
irq_arbiter: process(clk_i)
begin
if rising_edge(clk_i) then
cpu_irq_o <= '0';
if (irq_run = '0') then -- no active IRQ
if (irq_fire = '1') then
cpu_irq_o <= '1';
irq_run <= '1';
irq_src <= irq_src_nxt;
end if;
else -- active IRQ, wait for CPU to acknowledge
if (wren = '1') and (addr = xirq_source_addr_c) then -- write _any_ value to acknowledge
irq_run <= '0';
end if;
end if;
end if;
end process irq_arbiter;
end neorv32_xirq_rtl;

View File

@ -0,0 +1,35 @@
# SoC/Processor Templates
This folder provides exemplary templates that wrap the processor top entity and provide a simplified
set of configuration generics and IOs. These setups are intended to allow beginner an easy start by
hiding much of the processor's configuration complexity. Furthermore, these setups are used by many
of the provided [example setups](https://github.com/stnolting/neorv32/tree/master/setups).
Alternatively, you can directly instantiate the processor's top entity
[`rtl/core/neorv32_top.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd)
to have full access to _all_ features.
### [`neorv32_ProcessorTop_Minimal.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/processor_templates/neorv32_ProcessorTop_Minimal.vhd)
This setup used the ["Direct Boot Configuration"](https://stnolting.github.io/neorv32/#_boot_configuration).
Application software is installed directly into the processor-internal instruction memory (IMEM) during
synthesis. This memory is implemented as ROM and these is no bootloader available. Hence, the executable
remains unchangeable is executed right after reset.
The setup only provides 3 PWM channels as IO.
### [`neorv32_ProcessorTop_MinimalBoot.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/processor_templates/neorv32_ProcessorTop_MinimalBoot.vhd)
This setup used the ["Indirect Boot Configuration"](https://stnolting.github.io/neorv32/#_boot_configuration).
The NEORV32 bootloader is enabled in this setup allowing to upload new application software at any time
via a UART connection.
The setup provides 8 GPIO outputs and the UART communication lines as IO.
### [`neorv32_ProcessorTop_UP5KDemo.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/processor_templates/neorv32_ProcessorTop_UP5KDemo.vhd)
This is a more complex template that implements a small microcontroller-like NEORV32.
It was originally designed for _UPDuino V3_ board, which features a Lattice iCE40up5k FPGA, but has
also been ported to other boards that provide the same FPGA.
This setup provides a rich set of IOs including GPIO, SPI, TWI and PWM.

View File

@ -0,0 +1,246 @@
-- #################################################################################################
-- # << NEORV32 - Minimal setup without a bootloader >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
entity neorv32_ProcessorTop_Minimal is
generic (
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
HW_THREAD_ID : natural := 0; -- hardware thread id (32-bit)
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural := 34; -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 8*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (0..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN : boolean := true; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 8*1024; -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN : boolean := true; -- implement processor-internal data memory
MEM_INT_DMEM_SIZE : natural := 64*1024; -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN : boolean := false; -- implement instruction cache
ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE : natural := 64; -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY : natural := 1; -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- Processor peripherals --
IO_MTIME_EN : boolean := false; -- implement machine system timer (MTIME)?
IO_PWM_NUM_CH : natural := 3; -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN : boolean := false -- implement watch dog timer (WDT)?
);
port (
clk_i : in std_logic;
rstn_i : in std_logic;
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o : out std_ulogic_vector(IO_PWM_NUM_CH-1 downto 0)
);
end entity;
architecture neorv32_ProcessorTop_Minimal_rtl of neorv32_ProcessorTop_Minimal is
begin
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity neorv32.neorv32_top
generic map (
-- General --
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN => false, -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id (32-bit)
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN => false, -- implement on-chip debugger?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr => true, -- implement base counters?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH, -- total size of HPM counters (1..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN => ICACHE_EN, -- implement instruction cache
ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY => ICACHE_ASSOCIATIVITY, -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- External memory interface --
MEM_EXT_EN => false, -- implement external memory bus interface?
MEM_EXT_TIMEOUT => 0, -- cycles after a pending bus access auto-terminates (0 = disabled)
-- Processor peripherals --
IO_GPIO_EN => false, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => IO_MTIME_EN, -- implement machine system timer (MTIME)?
IO_UART0_EN => false, -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART1_EN => false, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_SPI_EN => false, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => false, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => IO_PWM_NUM_CH, -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN => IO_WDT_EN, -- implement watch dog timer (WDT)?
IO_TRNG_EN => false, -- implement true random number generator (TRNG)?
IO_CFS_EN => false, -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG => x"00000000", -- custom CFS configuration generic
IO_CFS_IN_SIZE => 32, -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE => 32, -- size of CFS output conduit in bits
IO_NEOLED_EN => false -- implement NeoPixel-compatible smart LED interface (NEOLED)?
)
port map (
-- Global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
-- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) --
jtag_trst_i => '0', -- low-active TAP reset (optional)
jtag_tck_i => '0', -- serial clock
jtag_tdi_i => '0', -- serial data input
jtag_tdo_o => open, -- serial data output
jtag_tms_i => '0', -- mode select
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
wb_tag_o => open, -- request tag
wb_adr_o => open, -- address
wb_dat_i => (others => '0'), -- read data
wb_dat_o => open, -- write data
wb_we_o => open, -- read/write
wb_sel_o => open, -- byte enable
wb_stb_o => open, -- strobe
wb_cyc_o => open, -- valid cycle
wb_lock_o => open, -- exclusive access request
wb_ack_i => '0', -- transfer acknowledge
wb_err_i => '0', -- transfer error
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => open, -- indicates an executed FENCE operation
fencei_o => open, -- indicates an executed FENCEI operation
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o => open, -- parallel output
gpio_i => (others => '0'), -- parallel input
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o => open, -- UART0 send data
uart0_rxd_i => '0', -- UART0 receive data
uart0_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o => open, -- UART1 send data
uart1_rxd_i => '0', -- UART1 receive data
uart1_rts_o => open, -- hw flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_cts_i => '0', -- hw flow control: UART1.TX allowed to transmit, low-active, optional
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o => open, -- SPI serial clock
spi_sdo_o => open, -- controller data out, peripheral data in
spi_sdi_i => '0', -- controller data in, peripheral data out
spi_csn_o => open, -- SPI CS
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io => open, -- twi serial data line
twi_scl_io => open, -- twi serial clock line
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o => pwm_o, -- pwm channels
-- Custom Functions Subsystem IO --
cfs_in_i => (others => '0'), -- custom CFS inputs conduit
cfs_out_o => open, -- custom CFS outputs conduit
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o => open, -- async serial data line
-- System time --
mtime_i => (others => '0'), -- current system time from ext. MTIME (if IO_MTIME_EN = false)
mtime_o => open, -- current system time from int. MTIME (if IO_MTIME_EN = true)
-- Interrupts --
mtime_irq_i => '0', -- machine timer interrupt, available if IO_MTIME_EN = false
msw_irq_i => '0', -- machine software interrupt
mext_irq_i => '0' -- machine external interrupt
);
end architecture;

View File

@ -0,0 +1,267 @@
-- #################################################################################################
-- # << NEORV32 - Minimal setup with the bootloader enabled >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
entity neorv32_ProcessorTop_MinimalBoot is
generic (
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN : boolean := true; -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
HW_THREAD_ID : natural := 0; -- hardware thread id (32-bit)
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := true; -- implement atomic extension?
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := true; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural := 34; -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (0..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN : boolean := true; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 64*1024; -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN : boolean := true; -- implement processor-internal data memory
MEM_INT_DMEM_SIZE : natural := 64*1024; -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN : boolean := false; -- implement instruction cache
ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE : natural := 64; -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY : natural := 1; -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- Processor peripherals --
IO_GPIO_EN : boolean := true; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := true; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := true; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_PWM_NUM_CH : natural := 3; -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN : boolean := true -- implement watch dog timer (WDT)?
);
port (
clk_i : in std_logic;
rstn_i : in std_logic;
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o : out std_ulogic_vector(3 downto 0);
-- primary UART0 (available if IO_UART0_EN = true) --
uart_txd_o : out std_ulogic; -- UART0 send data
uart_rxd_i : in std_ulogic := '0'; -- UART0 receive data
uart_rts_o : out std_ulogic; -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i : in std_ulogic := '0'; -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o : out std_ulogic_vector(IO_PWM_NUM_CH-1 downto 0)
);
end entity;
architecture neorv32_ProcessorTop_MinimalBoot_rtl of neorv32_ProcessorTop_MinimalBoot is
-- internal IO connection --
signal con_gpio_o : std_ulogic_vector(63 downto 0);
begin
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- GPIO --
gpio_o <= con_gpio_o(3 downto 0);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity neorv32.neorv32_top
generic map (
-- General --
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN => INT_BOOTLOADER_EN,-- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id (32-bit)
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN => false, -- implement on-chip debugger?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr => true, -- implement base counters?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH, -- total size of HPM counters (1..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN => ICACHE_EN, -- implement instruction cache
ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY => ICACHE_ASSOCIATIVITY, -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- External memory interface --
MEM_EXT_EN => false, -- implement external memory bus interface?
MEM_EXT_TIMEOUT => 0, -- cycles after a pending bus access auto-terminates (0 = disabled)
-- Processor peripherals --
IO_GPIO_EN => IO_GPIO_EN, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => IO_MTIME_EN, -- implement machine system timer (MTIME)?
IO_UART0_EN => IO_UART0_EN, -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART1_EN => false, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_SPI_EN => false, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => false, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => IO_PWM_NUM_CH, -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN => IO_WDT_EN, -- implement watch dog timer (WDT)?
IO_TRNG_EN => false, -- implement true random number generator (TRNG)?
IO_CFS_EN => false, -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG => x"00000000", -- custom CFS configuration generic
IO_CFS_IN_SIZE => 32, -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE => 32, -- size of CFS output conduit in bits
IO_NEOLED_EN => false -- implement NeoPixel-compatible smart LED interface (NEOLED)?
)
port map (
-- Global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
-- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) --
jtag_trst_i => '0', -- low-active TAP reset (optional)
jtag_tck_i => '0', -- serial clock
jtag_tdi_i => '0', -- serial data input
jtag_tdo_o => open, -- serial data output
jtag_tms_i => '0', -- mode select
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
wb_tag_o => open, -- request tag
wb_adr_o => open, -- address
wb_dat_i => (others => '0'), -- read data
wb_dat_o => open, -- write data
wb_we_o => open, -- read/write
wb_sel_o => open, -- byte enable
wb_stb_o => open, -- strobe
wb_cyc_o => open, -- valid cycle
wb_lock_o => open, -- exclusive access request
wb_ack_i => '0', -- transfer acknowledge
wb_err_i => '0', -- transfer error
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => open, -- indicates an executed FENCE operation
fencei_o => open, -- indicates an executed FENCEI operation
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o => con_gpio_o, -- parallel output
gpio_i => (others => '0'), -- parallel input
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o => uart_txd_o, -- UART0 send data
uart0_rxd_i => uart_rxd_i, -- UART0 receive data
uart0_rts_o => uart_rts_o, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_cts_i => uart_cts_i, -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o => open, -- UART1 send data
uart1_rxd_i => '0', -- UART1 receive data
uart1_rts_o => open, -- hw flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_cts_i => '0', -- hw flow control: UART1.TX allowed to transmit, low-active, optional
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o => open, -- SPI serial clock
spi_sdo_o => open, -- controller data out, peripheral data in
spi_sdi_i => '0', -- controller data in, peripheral data out
spi_csn_o => open, -- SPI CS
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io => open, -- twi serial data line
twi_scl_io => open, -- twi serial clock line
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o => pwm_o, -- pwm channels
-- Custom Functions Subsystem IO --
cfs_in_i => (others => '0'), -- custom CFS inputs conduit
cfs_out_o => open, -- custom CFS outputs conduit
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o => open, -- async serial data line
-- System time --
mtime_i => (others => '0'), -- current system time from ext. MTIME (if IO_MTIME_EN = false)
mtime_o => open, -- current system time from int. MTIME (if IO_MTIME_EN = true)
-- Interrupts --
mtime_irq_i => '0', -- machine timer interrupt, available if IO_MTIME_EN = false
msw_irq_i => '0', -- machine software interrupt
mext_irq_i => '0' -- machine external interrupt
);
end architecture;

View File

@ -0,0 +1,307 @@
-- #################################################################################################
-- # << NEORV32 - Example setup for boards with UP5K devices >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
entity neorv32_ProcessorTop_UP5KDemo is
generic (
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
HW_THREAD_ID : natural := 0; -- hardware thread id (32-bit)
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN : boolean := false; -- implement on-chip debugger?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := true; -- implement atomic extension?
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := true; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural := 34; -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (0..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN : boolean := true; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 64*1024; -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN : boolean := true; -- implement processor-internal data memory
MEM_INT_DMEM_SIZE : natural := 64*1024; -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN : boolean := false; -- implement instruction cache
ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE : natural := 64; -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY : natural := 1; -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- Processor peripherals --
IO_GPIO_EN : boolean := true; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := true; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := true; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_SPI_EN : boolean := true; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean := true; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural := 3; -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN : boolean := true -- implement watch dog timer (WDT)?
);
port (
clk_i : in std_logic;
rstn_i : in std_logic;
-- GPIO (available if IO_GPIO_EN = true) --
gpio_i : in std_ulogic_vector(3 downto 0);
gpio_o : out std_ulogic_vector(3 downto 0);
-- primary UART0 (available if IO_UART0_EN = true) --
uart_txd_o : out std_ulogic; -- UART0 send data
uart_rxd_i : in std_ulogic := '0'; -- UART0 receive data
uart_rts_o : out std_ulogic; -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i : in std_ulogic := '0'; -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- SPI to on-board flash --
flash_sck_o : out std_ulogic;
flash_sdo_o : out std_ulogic;
flash_sdi_i : in std_ulogic;
flash_csn_o : out std_ulogic; -- NEORV32.SPI_CS(0)
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o : out std_ulogic;
spi_sdo_o : out std_ulogic;
spi_sdi_i : in std_ulogic;
spi_csn_o : out std_ulogic; -- NEORV32.SPI_CS(1)
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io : inout std_logic;
twi_scl_io : inout std_logic;
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o : out std_ulogic_vector(IO_PWM_NUM_CH-1 downto 0)
);
end entity;
architecture neorv32_ProcessorTop_UP5KDemo_rtl of neorv32_ProcessorTop_UP5KDemo is
-- internal IO connection --
signal con_gpio_o : std_ulogic_vector(63 downto 0);
signal con_gpio_i : std_ulogic_vector(63 downto 0);
signal con_spi_sck : std_ulogic;
signal con_spi_sdi : std_ulogic;
signal con_spi_sdo : std_ulogic;
signal con_spi_csn : std_ulogic_vector(07 downto 0);
begin
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- SPI: on-board flash --
flash_sck_o <= con_spi_sck;
flash_sdo_o <= con_spi_sdo;
flash_csn_o <= con_spi_csn(0);
-- SPI: user port --
spi_sck_o <= con_spi_sck;
spi_sdo_o <= con_spi_sdo;
spi_csn_o <= con_spi_csn(1);
con_spi_sdi <= flash_sdi_i when (con_spi_csn(0) = '0') else spi_sdi_i;
-- GPIO --
gpio_o <= con_gpio_o(3 downto 0);
con_gpio_i(03 downto 0) <= gpio_i;
con_gpio_i(63 downto 4) <= (others => '0');
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity neorv32.neorv32_top
generic map (
-- General --
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN => true, -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id (32-bit)
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN => ON_CHIP_DEBUGGER_EN, -- implement on-chip debugger?
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr => true, -- implement base counters?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH, -- total size of HPM counters (1..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN => ICACHE_EN, -- implement instruction cache
ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY => ICACHE_ASSOCIATIVITY, -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- External memory interface --
MEM_EXT_EN => false, -- implement external memory bus interface?
MEM_EXT_TIMEOUT => 0, -- cycles after a pending bus access auto-terminates (0 = disabled)
-- Processor peripherals --
IO_GPIO_EN => IO_GPIO_EN, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => IO_MTIME_EN, -- implement machine system timer (MTIME)?
IO_UART0_EN => IO_UART0_EN, -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART1_EN => false, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_SPI_EN => IO_SPI_EN, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => IO_TWI_EN, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => IO_PWM_NUM_CH, -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN => IO_WDT_EN, -- implement watch dog timer (WDT)?
IO_TRNG_EN => false, -- implement true random number generator (TRNG)?
IO_CFS_EN => false, -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG => x"00000000", -- custom CFS configuration generic
IO_CFS_IN_SIZE => 32, -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE => 32, -- size of CFS output conduit in bits
IO_NEOLED_EN => false -- implement NeoPixel-compatible smart LED interface (NEOLED)?
)
port map (
-- Global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
-- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) --
jtag_trst_i => '0', -- low-active TAP reset (optional)
jtag_tck_i => '0', -- serial clock
jtag_tdi_i => '0', -- serial data input
jtag_tdo_o => open, -- serial data output
jtag_tms_i => '0', -- mode select
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
wb_tag_o => open, -- request tag
wb_adr_o => open, -- address
wb_dat_i => (others => '0'), -- read data
wb_dat_o => open, -- write data
wb_we_o => open, -- read/write
wb_sel_o => open, -- byte enable
wb_stb_o => open, -- strobe
wb_cyc_o => open, -- valid cycle
wb_lock_o => open, -- exclusive access request
wb_ack_i => '0', -- transfer acknowledge
wb_err_i => '0', -- transfer error
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => open, -- indicates an executed FENCE operation
fencei_o => open, -- indicates an executed FENCEI operation
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o => con_gpio_o, -- parallel output
gpio_i => con_gpio_i, -- parallel input
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o => uart_txd_o, -- UART0 send data
uart0_rxd_i => uart_rxd_i, -- UART0 receive data
uart0_rts_o => uart_rts_o, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_cts_i => uart_cts_i, -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o => open, -- UART1 send data
uart1_rxd_i => '0', -- UART1 receive data
uart1_rts_o => open, -- hw flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_cts_i => '0', -- hw flow control: UART1.TX allowed to transmit, low-active, optional
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o => con_spi_sck, -- SPI serial clock
spi_sdo_o => con_spi_sdo, -- controller data out, peripheral data in
spi_sdi_i => con_spi_sdi, -- controller data in, peripheral data out
spi_csn_o => con_spi_csn, -- SPI CS
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io => twi_sda_io, -- twi serial data line
twi_scl_io => twi_scl_io, -- twi serial clock line
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o => pwm_o, -- pwm channels
-- Custom Functions Subsystem IO --
cfs_in_i => (others => '0'), -- custom CFS inputs conduit
cfs_out_o => open, -- custom CFS outputs conduit
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o => open, -- async serial data line
-- System time --
mtime_i => (others => '0'), -- current system time from ext. MTIME (if IO_MTIME_EN = false)
mtime_o => open, -- current system time from int. MTIME (if IO_MTIME_EN = true)
-- Interrupts --
mtime_irq_i => '0', -- machine timer interrupt, available if IO_MTIME_EN = false
msw_irq_i => '0', -- machine software interrupt
mext_irq_i => '0' -- machine external interrupt
);
end architecture;

View File

@ -0,0 +1,486 @@
-- #################################################################################################
-- # << NEORV32 - Processor Top Entity with Resolved Port Signals (std_logic/std_logic_vector) >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_ProcessorTop_stdlogic is
generic (
-- General --
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN : boolean := true; -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
HW_THREAD_ID : natural := 0; -- hardware thread id (32-bit)
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN : boolean := false; -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr : boolean := true; -- implement base counters?
CPU_EXTENSION_RISCV_Zihpm : boolean := false; -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (0..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN : boolean := true; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN : boolean := true; -- implement processor-internal data memory
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN : boolean := false; -- implement instruction cache
ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE : natural := 64; -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY : natural := 1; -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- External memory interface --
MEM_EXT_EN : boolean := false; -- implement external memory bus interface?
MEM_EXT_TIMEOUT : natural := 255; -- cycles after a pending bus access auto-terminates (0 = disabled)
MEM_EXT_PIPE_MODE : boolean := false; -- protocol: false=classic/standard wishbone mode, true=pipelined wishbone mode
MEM_EXT_BIG_ENDIAN : boolean := false; -- byte order: true=big-endian, false=little-endian
MEM_EXT_ASYNC_RX : boolean := false; -- use register buffer for RX data when false
-- Stream link interface --
SLINK_NUM_TX : natural := 0; -- number of TX links (0..8)
SLINK_NUM_RX : natural := 0; -- number of TX links (0..8)
SLINK_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two
SLINK_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two
-- External Interrupts Controller (XIRQ) --
XIRQ_NUM_CH : natural := 0; -- number of external IRQ channels (0..32)
XIRQ_TRIGGER_TYPE : std_logic_vector(31 downto 0) := (others => '1'); -- trigger type: 0=level, 1=edge
XIRQ_TRIGGER_POLARITY : std_logic_vector(31 downto 0) := (others => '1'); -- trigger polarity: 0=low-level/falling-edge, 1=high-level/rising-edge
-- Processor peripherals --
IO_GPIO_EN : boolean := true; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := true; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := true; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN : boolean := true; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN : boolean := true; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean := true; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural := 4; -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)?
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)?
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits
IO_NEOLED_EN : boolean := true; -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_GPTMR_EN : boolean := false -- implement general purpose timer (GPTMR)?
);
port (
-- Global control --
clk_i : in std_logic := '0'; -- global clock, rising edge
rstn_i : in std_logic := '0'; -- global reset, low-active, async
-- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) --
jtag_trst_i : in std_logic := '0'; -- low-active TAP reset (optional)
jtag_tck_i : in std_logic := '0'; -- serial clock
jtag_tdi_i : in std_logic := '0'; -- serial data input
jtag_tdo_o : out std_logic; -- serial data output
jtag_tms_i : in std_logic := '0'; -- mode select
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
wb_tag_o : out std_logic_vector(02 downto 0); -- tag
wb_adr_o : out std_logic_vector(31 downto 0); -- address
wb_dat_i : in std_logic_vector(31 downto 0) := (others => '0'); -- read data
wb_dat_o : out std_logic_vector(31 downto 0); -- write data
wb_we_o : out std_logic; -- read/write
wb_sel_o : out std_logic_vector(03 downto 0); -- byte enable
wb_stb_o : out std_logic; -- strobe
wb_cyc_o : out std_logic; -- valid cycle
wb_lock_o : out std_logic; -- exclusive access request
wb_ack_i : in std_logic := '0'; -- transfer acknowledge
wb_err_i : in std_logic := '0'; -- transfer error
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o : out std_logic; -- indicates an executed FENCE operation
fencei_o : out std_logic; -- indicates an executed FENCEI operation
-- TX stream interfaces (available if SLINK_NUM_TX > 0) --
slink_tx_dat_o : out sdata_8x32r_t; -- output data
slink_tx_val_o : out std_logic_vector(7 downto 0); -- valid output
slink_tx_rdy_i : in std_logic_vector(7 downto 0) := (others => '0'); -- ready to send
-- RX stream interfaces (available if SLINK_NUM_RX > 0) --
slink_rx_dat_i : in sdata_8x32r_t := (others => (others => '0')); -- input data
slink_rx_val_i : in std_logic_vector(7 downto 0) := (others => '0'); -- valid input
slink_rx_rdy_o : out std_logic_vector(7 downto 0); -- ready to receive
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o : out std_logic_vector(63 downto 0); -- parallel output
gpio_i : in std_logic_vector(63 downto 0) := (others => '0'); -- parallel input
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o : out std_logic; -- UART0 send data
uart0_rxd_i : in std_logic := '0'; -- UART0 receive data
uart0_rts_o : out std_logic; -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_cts_i : in std_logic := '0'; -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o : out std_logic; -- UART1 send data
uart1_rxd_i : in std_logic := '0'; -- UART1 receive data
uart1_rts_o : out std_logic; -- hw flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_cts_i : in std_logic := '0'; -- hw flow control: UART1.TX allowed to transmit, low-active, optional
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o : out std_logic; -- SPI serial clock
spi_sdo_o : out std_logic; -- controller data out, peripheral data in
spi_sdi_i : in std_logic := '0'; -- controller data in, peripheral data out
spi_csn_o : out std_logic_vector(07 downto 0); -- SPI CS
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io : inout std_logic; -- twi serial data line
twi_scl_io : inout std_logic; -- twi serial clock line
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o : out std_logic_vector(IO_PWM_NUM_CH-1 downto 0); -- pwm channels
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) --
cfs_in_i : in std_logic_vector(IO_CFS_IN_SIZE-1 downto 0); -- custom inputs
cfs_out_o : out std_logic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom outputs
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o : out std_logic; -- async serial data line
-- System time --
mtime_i : in std_logic_vector(63 downto 0) := (others => '0'); -- current system time from ext. MTIME (if IO_MTIME_EN = false)
mtime_o : out std_logic_vector(63 downto 0); -- current system time from int. MTIME (if IO_MTIME_EN = true)
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
xirq_i : in std_logic_vector(XIRQ_NUM_CH-1 downto 0) := (others => '0'); -- IRQ channels
-- CPU Interrupts --
mtime_irq_i : in std_logic := '0'; -- machine timer interrupt, available if IO_MTIME_EN = false
msw_irq_i : in std_logic := '0'; -- machine software interrupt
mext_irq_i : in std_logic := '0' -- machine external interrupt
);
end entity;
architecture neorv32_ProcessorTop_stdlogic_rtl of neorv32_ProcessorTop_stdlogic is
-- type conversion --
constant IO_CFS_CONFIG_INT : std_ulogic_vector(31 downto 0) := std_ulogic_vector(IO_CFS_CONFIG);
constant XIRQ_TRIGGER_TYPE_INT : std_ulogic_vector(31 downto 0) := std_ulogic_vector(XIRQ_TRIGGER_TYPE);
constant XIRQ_TRIGGER_POLARITY_INT : std_ulogic_vector(31 downto 0) := std_ulogic_vector(XIRQ_TRIGGER_POLARITY);
--
signal clk_i_int : std_ulogic;
signal rstn_i_int : std_ulogic;
--
signal jtag_trst_i_int :std_ulogic;
signal jtag_tck_i_int :std_ulogic;
signal jtag_tdi_i_int :std_ulogic;
signal jtag_tdo_o_int :std_ulogic;
signal jtag_tms_i_int :std_ulogic;
--
signal wb_tag_o_int : std_ulogic_vector(02 downto 0);
signal wb_adr_o_int : std_ulogic_vector(31 downto 0);
signal wb_dat_i_int : std_ulogic_vector(31 downto 0);
signal wb_dat_o_int : std_ulogic_vector(31 downto 0);
signal wb_we_o_int : std_ulogic;
signal wb_sel_o_int : std_ulogic_vector(03 downto 0);
signal wb_stb_o_int : std_ulogic;
signal wb_cyc_o_int : std_ulogic;
signal wb_lock_o_int : std_ulogic;
signal wb_ack_i_int : std_ulogic;
signal wb_err_i_int : std_ulogic;
--
signal fence_o_int : std_ulogic;
signal fencei_o_int : std_ulogic;
--
signal slink_tx_dat_o_int : sdata_8x32_t;
signal slink_tx_val_o_int : std_logic_vector(7 downto 0);
signal slink_tx_rdy_i_int : std_logic_vector(7 downto 0);
signal slink_rx_dat_i_int : sdata_8x32_t;
signal slink_rx_val_i_int : std_logic_vector(7 downto 0);
signal slink_rx_rdy_o_int : std_logic_vector(7 downto 0);
--
signal gpio_o_int : std_ulogic_vector(63 downto 0);
signal gpio_i_int : std_ulogic_vector(63 downto 0);
--
signal uart0_txd_o_int : std_ulogic;
signal uart0_rxd_i_int : std_ulogic;
signal uart0_rts_o_int : std_ulogic;
signal uart0_cts_i_int : std_ulogic;
--
signal uart1_txd_o_int : std_ulogic;
signal uart1_rxd_i_int : std_ulogic;
signal uart1_rts_o_int : std_ulogic;
signal uart1_cts_i_int : std_ulogic;
--
signal spi_sck_o_int : std_ulogic;
signal spi_sdo_o_int : std_ulogic;
signal spi_sdi_i_int : std_ulogic;
signal spi_csn_o_int : std_ulogic_vector(07 downto 0);
--
signal pwm_o_int : std_ulogic_vector(IO_PWM_NUM_CH-1 downto 0);
--
signal cfs_in_i_int : std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0);
signal cfs_out_o_int : std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0);
--
signal neoled_o_int : std_ulogic;
--
signal mtime_i_int : std_ulogic_vector(63 downto 0);
signal mtime_o_int : std_ulogic_vector(63 downto 0);
--
signal xirq_i_int : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
--
signal mtime_irq_i_int : std_ulogic;
signal msw_irq_i_int : std_ulogic;
signal mext_irq_i_int : std_ulogic;
begin
-- The Core Of The Problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_top_inst: neorv32_top
generic map (
-- General --
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN => INT_BOOTLOADER_EN, -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id (hartid) (32-bit)
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN => ON_CHIP_DEBUGGER_EN, -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr, -- implement base counters?
CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm, -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH, -- total size of HPM counters (0..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN => ICACHE_EN, -- implement instruction cache
ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY => ICACHE_ASSOCIATIVITY, -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- External memory interface --
MEM_EXT_EN => MEM_EXT_EN, -- implement external memory bus interface?
MEM_EXT_TIMEOUT => MEM_EXT_TIMEOUT, -- cycles after a pending bus access auto-terminates (0 = disabled)
MEM_EXT_PIPE_MODE => MEM_EXT_PIPE_MODE, -- protocol: false=classic/standard wishbone mode, true=pipelined wishbone mode
MEM_EXT_BIG_ENDIAN => MEM_EXT_BIG_ENDIAN, -- byte order: true=big-endian, false=little-endian
MEM_EXT_ASYNC_RX => MEM_EXT_ASYNC_RX, -- use register buffer for RX data when false
-- Stream link interface --
SLINK_NUM_TX => SLINK_NUM_TX, -- number of TX links (0..8)
SLINK_NUM_RX => SLINK_NUM_RX, -- number of TX links (0..8)
SLINK_TX_FIFO => SLINK_TX_FIFO, -- TX fifo depth, has to be a power of two
SLINK_RX_FIFO => SLINK_RX_FIFO, -- RX fifo depth, has to be a power of two
-- External Interrupts Controller (XIRQ) --
XIRQ_NUM_CH => XIRQ_NUM_CH, -- number of external IRQ channels (0..32)
XIRQ_TRIGGER_TYPE => XIRQ_TRIGGER_TYPE_INT, -- trigger type: 0=level, 1=edge
XIRQ_TRIGGER_POLARITY => XIRQ_TRIGGER_POLARITY_INT, -- trigger polarity: 0=low-level/falling-edge, 1=high-level/rising-edge
-- Processor peripherals --
IO_GPIO_EN => IO_GPIO_EN, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => IO_MTIME_EN, -- implement machine system timer (MTIME)?
IO_UART0_EN => IO_UART0_EN, -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO => IO_UART0_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO => IO_UART0_TX_FIFO, -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN => IO_UART1_EN, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO => IO_UART1_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO => IO_UART1_TX_FIFO, -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN => IO_SPI_EN, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => IO_TWI_EN, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => IO_PWM_NUM_CH, -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN => IO_WDT_EN, -- implement watch dog timer (WDT)?
IO_TRNG_EN => IO_TRNG_EN, -- implement true random number generator (TRNG)?
IO_CFS_EN => IO_CFS_EN, -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG => IO_CFS_CONFIG_INT, -- custom CFS configuration generic
IO_CFS_IN_SIZE => IO_CFS_IN_SIZE, -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE => IO_CFS_OUT_SIZE, -- size of CFS output conduit in bits
IO_NEOLED_EN => IO_NEOLED_EN, -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_GPTMR_EN => IO_GPTMR_EN -- implement general purpose timer (GPTMR)?
)
port map (
-- Global control --
clk_i => clk_i_int, -- global clock, rising edge
rstn_i => rstn_i_int, -- global reset, low-active, async
-- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) --
jtag_trst_i => jtag_trst_i_int, -- low-active TAP reset (optional)
jtag_tck_i => jtag_tck_i_int, -- serial clock
jtag_tdi_i => jtag_tdi_i_int, -- serial data input
jtag_tdo_o => jtag_tdo_o_int, -- serial data output
jtag_tms_i => jtag_tms_i_int, -- mode select
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
wb_tag_o => wb_tag_o_int, -- tag
wb_adr_o => wb_adr_o_int, -- address
wb_dat_i => wb_dat_i_int, -- read data
wb_dat_o => wb_dat_o_int, -- write data
wb_we_o => wb_we_o_int, -- read/write
wb_sel_o => wb_sel_o_int, -- byte enable
wb_stb_o => wb_stb_o_int, -- strobe
wb_cyc_o => wb_cyc_o_int, -- valid cycle
wb_lock_o => wb_lock_o_int, -- exclusive access request
wb_ack_i => wb_ack_i_int, -- transfer acknowledge
wb_err_i => wb_err_i_int, -- transfer error
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => fence_o_int, -- indicates an executed FENCE operation
fencei_o => fencei_o_int, -- indicates an executed FENCEI operation
-- TX stream interfaces (available if SLINK_NUM_TX > 0) --
slink_tx_dat_o => slink_tx_dat_o_int, -- output data
slink_tx_val_o => slink_tx_val_o_int, -- valid output
slink_tx_rdy_i => slink_tx_rdy_i_int, -- ready to send
-- RX stream interfaces (available if SLINK_NUM_RX > 0) --
slink_rx_dat_i => slink_rx_dat_i_int, -- input data
slink_rx_val_i => slink_rx_val_i_int, -- valid input
slink_rx_rdy_o => slink_rx_rdy_o_int, -- ready to receive
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o => gpio_o_int, -- parallel output
gpio_i => gpio_i_int, -- parallel input
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o => uart0_txd_o_int, -- UART0 send data
uart0_rxd_i => uart0_rxd_i_int, -- UART0 receive data
uart0_rts_o => uart0_rts_o_int, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_cts_i => uart0_cts_i_int, -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o => uart1_txd_o_int, -- UART1 send data
uart1_rxd_i => uart1_rxd_i_int, -- UART1 receive data
uart1_rts_o => uart1_rts_o_int, -- hw flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_cts_i => uart1_cts_i_int, -- hw flow control: UART1.TX allowed to transmit, low-active, optional
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o => spi_sck_o_int, -- SPI serial clock
spi_sdo_o => spi_sdo_o_int, -- controller data out, peripheral data in
spi_sdi_i => spi_sdi_i_int, -- controller data in, peripheral data out
spi_csn_o => spi_csn_o_int, -- SPI CS
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io => twi_sda_io, -- twi serial data line
twi_scl_io => twi_scl_io, -- twi serial clock line
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o => pwm_o_int, -- pwm channels
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) --
cfs_in_i => cfs_in_i_int, -- custom inputs
cfs_out_o => cfs_out_o_int, -- custom outputs
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o => neoled_o_int, -- async serial data line
-- System time --
mtime_i => mtime_i_int, -- current system time from ext. MTIME (if IO_MTIME_EN = false)
mtime_o => mtime_o_int, -- current system time from int. MTIME (if IO_MTIME_EN = true)
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
xirq_i => xirq_i_int, -- IRQ channels
-- CPU Interrupts --
mtime_irq_i => mtime_irq_i_int, -- machine timer interrupt, available if IO_MTIME_EN = false
msw_irq_i => msw_irq_i_int, -- machine software interrupt
mext_irq_i => mext_irq_i_int -- machine external interrupt
);
-- type conversion --
clk_i_int <= std_ulogic(clk_i);
rstn_i_int <= std_ulogic(rstn_i);
jtag_trst_i_int <= std_ulogic(jtag_trst_i);
jtag_tck_i_int <= std_ulogic(jtag_tck_i);
jtag_tdi_i_int <= std_ulogic(jtag_tdi_i);
jtag_tdo_o <= std_logic(jtag_tdo_o_int);
jtag_tms_i_int <= std_ulogic(jtag_tms_i);
wb_tag_o <= std_logic_vector(wb_tag_o_int);
wb_adr_o <= std_logic_vector(wb_adr_o_int);
wb_dat_i_int <= std_ulogic_vector(wb_dat_i);
wb_dat_o <= std_logic_vector(wb_dat_o_int);
wb_we_o <= std_logic(wb_we_o_int);
wb_sel_o <= std_logic_vector(wb_sel_o_int);
wb_stb_o <= std_logic(wb_stb_o_int);
wb_cyc_o <= std_logic(wb_cyc_o_int);
wb_lock_o <= std_logic(wb_lock_o_int);
wb_ack_i_int <= std_ulogic(wb_ack_i);
wb_err_i_int <= std_ulogic(wb_err_i);
fence_o <= std_logic(fence_o_int);
fencei_o <= std_logic(fencei_o_int);
slink_tx_val_o <= std_logic_vector(slink_tx_val_o_int);
slink_tx_rdy_i_int <= std_ulogic_vector(slink_tx_rdy_i);
slink_rx_val_i_int <= std_ulogic_vector(slink_rx_val_i);
slink_rx_rdy_o <= std_logic_vector(slink_rx_rdy_o_int);
slink_conv:
for i in 0 to 7 generate
slink_tx_dat_o(i) <= std_logic_vector(slink_tx_dat_o_int(i));
slink_rx_dat_i_int(i) <= std_ulogic_vector(slink_rx_dat_i(i));
end generate;
gpio_o <= std_logic_vector(gpio_o_int);
gpio_i_int <= std_ulogic_vector(gpio_i);
uart0_txd_o <= std_logic(uart0_txd_o_int);
uart0_rxd_i_int <= std_ulogic(uart0_rxd_i);
uart0_rts_o <= std_logic(uart0_rts_o_int);
uart0_cts_i_int <= std_ulogic(uart0_cts_i);
uart1_txd_o <= std_logic(uart1_txd_o_int);
uart1_rxd_i_int <= std_ulogic(uart1_rxd_i);
uart1_rts_o <= std_logic(uart1_rts_o_int);
uart1_cts_i_int <= std_ulogic(uart1_cts_i);
spi_sck_o <= std_logic(spi_sck_o_int);
spi_sdo_o <= std_logic(spi_sdo_o_int);
spi_sdi_i_int <= std_ulogic(spi_sdi_i);
spi_csn_o <= std_logic_vector(spi_csn_o_int);
pwm_o <= std_logic_vector(pwm_o_int);
cfs_in_i_int <= std_ulogic_vector(cfs_in_i);
cfs_out_o <= std_logic_vector(cfs_out_o_int);
neoled_o <= std_logic(neoled_o_int);
mtime_i_int <= std_ulogic_vector(mtime_i);
mtime_o <= std_logic_vector(mtime_o_int);
xirq_i_int <= std_ulogic_vector(xirq_i);
msw_irq_i_int <= std_ulogic(msw_irq_i);
mext_irq_i_int <= std_ulogic(mext_irq_i);
end architecture;

View File

@ -0,0 +1,423 @@
-- #################################################################################################
-- # << NEORV32 - Processor Top Entity with AvalonMM Compatible Master Interface >> #
-- # ********************************************************************************************* #
-- # (c) "AvalonMM", "NIOS-2", "Qsys", "MegaWizard" and "Platform Designer" #
-- # are trademarks of Intel #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_top_avalonmm is
generic (
-- General --
CLOCK_FREQUENCY : natural; -- clock frequency of clk_i in Hz
HW_THREAD_ID : natural := 0; -- hardware thread id (32-bit)
INT_BOOTLOADER_EN : boolean := false; -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN : boolean := false; -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT regs!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr : boolean := true; -- implement base counters?
CPU_EXTENSION_RISCV_Zihpm : boolean := false; -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
CPU_EXTENSION_RISCV_Zmmul : boolean := false; -- implement multiply-only M sub-extension?
-- Extension Options --
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES : natural := 2; -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (0..64)
-- Internal Instruction memory (IMEM) --
MEM_INT_IMEM_EN : boolean := false; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes
-- Internal Data memory (DMEM) --
MEM_INT_DMEM_EN : boolean := false; -- implement processor-internal data memory
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes
-- Internal Cache memory (iCACHE) --
ICACHE_EN : boolean := false; -- implement instruction cache
ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE : natural := 64; -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY : natural := 1; -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- Stream link interface (SLINK) --
SLINK_NUM_TX : natural := 0; -- number of TX links (0..8)
SLINK_NUM_RX : natural := 0; -- number of TX links (0..8)
SLINK_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two
SLINK_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two
-- External Interrupts Controller (XIRQ) --
XIRQ_NUM_CH : natural := 0; -- number of external IRQ channels (0..32)
XIRQ_TRIGGER_TYPE : std_ulogic_vector(31 downto 0) := x"ffffffff"; -- trigger type: 0=level, 1=edge
XIRQ_TRIGGER_POLARITY : std_ulogic_vector(31 downto 0) := x"ffffffff"; -- trigger polarity: 0=low-level/falling-edge, 1=high-level/rising-edge
-- Processor peripherals --
IO_GPIO_EN : boolean := false; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := false; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := false; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN : boolean := false; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN : boolean := false; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean := false; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural := 0; -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN : boolean := false; -- implement watch dog timer (WDT)?
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)?
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits
IO_NEOLED_EN : boolean := false; -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_TX_FIFO : natural := 1; -- NEOLED TX FIFO depth, 1..32k, has to be a power of two
IO_GPTMR_EN : boolean := false -- implement general purpose timer (GPTMR)?
);
port (
-- Global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
-- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) --
jtag_trst_i : in std_ulogic := 'U'; -- low-active TAP reset (optional)
jtag_tck_i : in std_ulogic := 'U'; -- serial clock
jtag_tdi_i : in std_ulogic := 'U'; -- serial data input
jtag_tdo_o : out std_ulogic; -- serial data output
jtag_tms_i : in std_ulogic := 'U'; -- mode select
-- AvalonMM interface
read_o : out std_logic;
write_o : out std_logic;
waitrequest_i : in std_logic := '0';
byteenable_o : out std_logic_vector(3 downto 0);
address_o : out std_logic_vector(31 downto 0);
writedata_o : out std_logic_vector(31 downto 0);
readdata_i : in std_logic_vector(31 downto 0) := (others => '0');
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o : out std_ulogic; -- indicates an executed FENCE operation
fencei_o : out std_ulogic; -- indicates an executed FENCEI operation
-- TX stream interfaces (available if SLINK_NUM_TX > 0) --
slink_tx_dat_o : out sdata_8x32_t; -- output data
slink_tx_val_o : out std_ulogic_vector(7 downto 0); -- valid output
slink_tx_rdy_i : in std_ulogic_vector(7 downto 0) := (others => 'L'); -- ready to send
-- RX stream interfaces (available if SLINK_NUM_RX > 0) --
slink_rx_dat_i : in sdata_8x32_t := (others => (others => 'U')); -- input data
slink_rx_val_i : in std_ulogic_vector(7 downto 0) := (others => 'L'); -- valid input
slink_rx_rdy_o : out std_ulogic_vector(7 downto 0); -- ready to receive
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o : out std_ulogic_vector(63 downto 0); -- parallel output
gpio_i : in std_ulogic_vector(63 downto 0) := (others => 'U'); -- parallel input
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o : out std_ulogic; -- UART0 send data
uart0_rxd_i : in std_ulogic := 'U'; -- UART0 receive data
uart0_rts_o : out std_ulogic; -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_cts_i : in std_ulogic := 'L'; -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o : out std_ulogic; -- UART1 send data
uart1_rxd_i : in std_ulogic := 'U'; -- UART1 receive data
uart1_rts_o : out std_ulogic; -- hw flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_cts_i : in std_ulogic := 'L'; -- hw flow control: UART1.TX allowed to transmit, low-active, optional
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o : out std_ulogic; -- SPI serial clock
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in
spi_sdi_i : in std_ulogic := 'U'; -- controller data in, peripheral data out
spi_csn_o : out std_ulogic_vector(07 downto 0); -- chip-select
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io : inout std_logic := 'U'; -- twi serial data line
twi_scl_io : inout std_logic := 'U'; -- twi serial clock line
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o : out std_ulogic_vector(IO_PWM_NUM_CH-1 downto 0); -- pwm channels
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) --
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0) := (others => 'U'); -- custom CFS inputs conduit
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom CFS outputs conduit
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o : out std_ulogic; -- async serial data line
-- System time --
mtime_i : in std_ulogic_vector(63 downto 0) := (others => 'U'); -- current system time from ext. MTIME (if IO_MTIME_EN = false)
mtime_o : out std_ulogic_vector(63 downto 0); -- current system time from int. MTIME (if IO_MTIME_EN = true)
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
xirq_i : in std_ulogic_vector(XIRQ_NUM_CH-1 downto 0) := (others => 'L'); -- IRQ channels
-- CPU interrupts --
mtime_irq_i : in std_ulogic := 'L'; -- machine timer interrupt, available if IO_MTIME_EN = false
msw_irq_i : in std_ulogic := 'L'; -- machine software interrupt
mext_irq_i : in std_ulogic := 'L' -- machine external interrupt
);
end neorv32_top_avalonmm;
architecture neorv32_top_avalonmm_rtl of neorv32_top_avalonmm is
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
signal wb_tag_o : std_ulogic_vector(02 downto 0); -- request tag
signal wb_adr_o : std_ulogic_vector(31 downto 0); -- address
signal wb_dat_i : std_ulogic_vector(31 downto 0) := (others => 'U'); -- read data
signal wb_dat_o : std_ulogic_vector(31 downto 0); -- write data
signal wb_we_o : std_ulogic; -- read/write
signal wb_sel_o : std_ulogic_vector(03 downto 0); -- byte enable
signal wb_stb_o : std_ulogic; -- strobe
signal wb_cyc_o : std_ulogic; -- valid cycle
signal wb_lock_o : std_ulogic; -- exclusive access request
signal wb_ack_i : std_ulogic := 'L'; -- transfer acknowledge
signal wb_err_i : std_ulogic := 'L'; -- transfer error
begin
neorv32_top_map : neorv32_top
generic map (
-- General --
CLOCK_FREQUENCY => CLOCK_FREQUENCY,
HW_THREAD_ID => HW_THREAD_ID,
INT_BOOTLOADER_EN => INT_BOOTLOADER_EN,
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN => ON_CHIP_DEBUGGER_EN,
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A,
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_Zicsr => CPU_EXTENSION_RISCV_Zicsr,
CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr,
CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm,
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei,
CPU_EXTENSION_RISCV_Zmmul => CPU_EXTENSION_RISCV_Zmmul,
-- Extension Options --
FAST_MUL_EN => FAST_MUL_EN,
FAST_SHIFT_EN => FAST_SHIFT_EN,
CPU_CNT_WIDTH => CPU_CNT_WIDTH,
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,
-- Internal Instruction memory (IMEM) --
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN,
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE,
-- Internal Data memory (DMEM) --
MEM_INT_DMEM_EN => MEM_INT_IMEM_EN,
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE,
-- Internal Cache memory (iCACHE) --
ICACHE_EN => ICACHE_EN,
ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS,
ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE,
ICACHE_ASSOCIATIVITY => ICACHE_ASSOCIATIVITY,
-- External memory interface (WISHBONE) --
MEM_EXT_EN => true,
MEM_EXT_TIMEOUT => 0,
MEM_EXT_PIPE_MODE => false,
MEM_EXT_BIG_ENDIAN => false,
MEM_EXT_ASYNC_RX => false,
-- Stream link interface (SLINK) --
SLINK_NUM_TX => SLINK_NUM_TX,
SLINK_NUM_RX => SLINK_NUM_RX,
SLINK_TX_FIFO => SLINK_TX_FIFO,
SLINK_RX_FIFO => SLINK_RX_FIFO,
-- External Interrupts Controller (XIRQ) --
XIRQ_NUM_CH => XIRQ_NUM_CH,
XIRQ_TRIGGER_TYPE => XIRQ_TRIGGER_TYPE,
XIRQ_TRIGGER_POLARITY => XIRQ_TRIGGER_POLARITY,
-- Processor peripherals --
IO_GPIO_EN => IO_GPIO_EN,
IO_MTIME_EN => IO_MTIME_EN,
IO_UART0_EN => IO_UART0_EN,
IO_UART0_RX_FIFO => IO_UART0_RX_FIFO,
IO_UART0_TX_FIFO => IO_UART0_TX_FIFO,
IO_UART1_EN => IO_UART1_EN,
IO_UART1_RX_FIFO => IO_UART1_RX_FIFO,
IO_UART1_TX_FIFO => IO_UART1_TX_FIFO,
IO_SPI_EN => IO_SPI_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_CFS_CONFIG => IO_CFS_CONFIG,
IO_CFS_IN_SIZE => IO_CFS_IN_SIZE,
IO_CFS_OUT_SIZE => IO_CFS_OUT_SIZE,
IO_NEOLED_EN => IO_NEOLED_EN,
IO_NEOLED_TX_FIFO => IO_NEOLED_TX_FIFO,
IO_GPTMR_EN => IO_GPTMR_EN
)
port map (
-- Global control --
clk_i => clk_i,
rstn_i => rstn_i,
-- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) --
jtag_trst_i => jtag_trst_i,
jtag_tck_i => jtag_tck_i,
jtag_tdi_i => jtag_tdi_i,
jtag_tdo_o => jtag_tdo_o,
jtag_tms_i => jtag_tms_i,
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
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_lock_o => wb_lock_o,
wb_ack_i => wb_ack_i,
wb_err_i => wb_err_i,
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => fence_o,
fencei_o => fencei_o,
-- TX stream interfaces (available if SLINK_NUM_TX > 0) --
slink_tx_dat_o => slink_tx_dat_o,
slink_tx_val_o => slink_tx_val_o,
slink_tx_rdy_i => slink_tx_rdy_i,
-- RX stream interfaces (available if SLINK_NUM_RX > 0) --
slink_rx_dat_i => slink_rx_dat_i,
slink_rx_val_i => slink_rx_val_i,
slink_rx_rdy_o => slink_rx_rdy_o,
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o => gpio_o,
gpio_i => gpio_i,
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o => uart0_txd_o,
uart0_rxd_i => uart0_rxd_i,
uart0_rts_o => uart0_rts_o,
uart0_cts_i => uart0_cts_i,
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o => uart1_txd_o,
uart1_rxd_i => uart1_rxd_i,
uart1_rts_o => uart1_rts_o,
uart1_cts_i => uart1_cts_i,
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o => spi_sck_o,
spi_sdo_o => spi_sdo_o,
spi_sdi_i => spi_sdi_i,
spi_csn_o => spi_csn_o,
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io => twi_sda_io,
twi_scl_io => twi_scl_io,
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o => pwm_o,
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) --
cfs_in_i => cfs_in_i,
cfs_out_o => cfs_out_o,
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o => neoled_o,
-- System time --
mtime_i => mtime_i,
mtime_o => mtime_o,
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
xirq_i => xirq_i,
-- CPU interrupts --
mtime_irq_i => mtime_irq_i,
msw_irq_i => msw_irq_i,
mext_irq_i => mext_irq_i
);
-- Wishbone to AvalonMM bridge
read_o <= '1' when (wb_stb_o = '1' and wb_we_o = '0') else '0';
write_o <= '1' when (wb_stb_o = '1' and wb_we_o = '1') else '0';
address_o <= std_logic_vector(wb_adr_o);
writedata_o <= std_logic_vector(wb_dat_o);
byteenable_o <= std_logic_vector(wb_sel_o);
wb_dat_i <= std_ulogic_vector(readdata_i);
wb_ack_i <= not(waitrequest_i);
wb_err_i <= '0';
end neorv32_top_avalonmm_rtl;

View File

@ -0,0 +1,532 @@
-- #################################################################################################
-- # << NEORV32 - Processor Top Entity with AXI4-Lite Compatible Master Interface >> #
-- # ********************************************************************************************* #
-- # (c) "AXI", "AXI4" and "AXI4-Lite" are trademarks of Arm Holdings plc. #
-- # Note: External MTIME is not supported. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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_SystemTop_axi4lite is
generic (
-- ------------------------------------------------------------
-- Configuration Generics --
-- ------------------------------------------------------------
-- General --
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN : boolean := true; -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
HW_THREAD_ID : natural := 0; -- hardware thread id (32-bit)
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN : boolean := false; -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr : boolean := true; -- implement base counters?
CPU_EXTENSION_RISCV_Zihpm : boolean := false; -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (0..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN : boolean := true; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN : boolean := true; -- implement processor-internal data memory
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN : boolean := false; -- implement instruction cache
ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE : natural := 64; -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY : natural := 1; -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- External Interrupts Controller (XIRQ) --
XIRQ_NUM_CH : natural := 0; -- number of external IRQ channels (0..32)
XIRQ_TRIGGER_TYPE : std_logic_vector(31 downto 0) := x"FFFFFFFF"; -- trigger type: 0=level, 1=edge
XIRQ_TRIGGER_POLARITY : std_logic_vector(31 downto 0) := x"FFFFFFFF"; -- trigger polarity: 0=low-level/falling-edge, 1=high-level/rising-edge
-- Processor peripherals --
IO_GPIO_EN : boolean := true; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := true; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := true; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN : boolean := true; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN : boolean := true; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean := true; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural := 4; -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)?
IO_TRNG_EN : boolean := true; -- implement true random number generator (TRNG)?
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG : std_logic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits
IO_NEOLED_EN : boolean := true; -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_TX_FIFO : natural := 1; -- NEOLED TX FIFO depth, 1..32k, has to be a power of two
IO_GPTMR_EN : boolean := false -- implement general purpose timer (GPTMR)?
);
port (
-- ------------------------------------------------------------
-- AXI4-Lite-Compatible Master Interface --
-- ------------------------------------------------------------
-- Clock and Reset --
m_axi_aclk : in std_logic;
m_axi_aresetn : in std_logic;
-- Write Address Channel --
m_axi_awaddr : out std_logic_vector(31 downto 0);
m_axi_awprot : out std_logic_vector(2 downto 0);
m_axi_awvalid : out std_logic;
m_axi_awready : in std_logic;
-- Write Data Channel --
m_axi_wdata : out std_logic_vector(31 downto 0);
m_axi_wstrb : out std_logic_vector(3 downto 0);
m_axi_wvalid : out std_logic;
m_axi_wready : in std_logic;
-- Read Address Channel --
m_axi_araddr : out std_logic_vector(31 downto 0);
m_axi_arprot : out std_logic_vector(2 downto 0);
m_axi_arvalid : out std_logic;
m_axi_arready : in std_logic;
-- Read Data Channel --
m_axi_rdata : in std_logic_vector(31 downto 0);
m_axi_rresp : in std_logic_vector(1 downto 0);
m_axi_rvalid : in std_logic;
m_axi_rready : out std_logic;
-- Write Response Channel --
m_axi_bresp : in std_logic_vector(1 downto 0);
m_axi_bvalid : in std_logic;
m_axi_bready : out std_logic;
-- ------------------------------------------------------------
-- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) --
-- ------------------------------------------------------------
jtag_trst_i : in std_logic := '0'; -- low-active TAP reset (optional)
jtag_tck_i : in std_logic := '0'; -- serial clock
jtag_tdi_i : in std_logic := '0'; -- serial data input
jtag_tdo_o : out std_logic; -- serial data output
jtag_tms_i : in std_logic := '0'; -- mode select
-- ------------------------------------------------------------
-- Processor IO --
-- ------------------------------------------------------------
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o : out std_logic_vector(63 downto 0); -- parallel output
gpio_i : in std_logic_vector(63 downto 0) := (others => '0'); -- parallel input
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o : out std_logic; -- UART0 send data
uart0_rxd_i : in std_logic := '0'; -- UART0 receive data
uart0_rts_o : out std_logic; -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_cts_i : in std_logic := '0'; -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o : out std_logic; -- UART1 send data
uart1_rxd_i : in std_logic := '0'; -- UART1 receive data
uart1_rts_o : out std_logic; -- hw flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_cts_i : in std_logic := '0'; -- hw flow control: UART1.TX allowed to transmit, low-active, optional
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o : out std_logic; -- SPI serial clock
spi_sdo_o : out std_logic; -- controller data out, peripheral data in
spi_sdi_i : in std_logic := '0'; -- controller data in, peripheral data out
spi_csn_o : out std_logic_vector(07 downto 0); -- SPI CS
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io : inout std_logic; -- twi serial data line
twi_scl_io : inout std_logic; -- twi serial clock line
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o : out std_logic_vector(IO_PWM_NUM_CH-1 downto 0); -- pwm channels
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) --
cfs_in_i : in std_logic_vector(IO_CFS_IN_SIZE-1 downto 0); -- custom inputs
cfs_out_o : out std_logic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom outputs
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o : out std_logic; -- async serial data line
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
xirq_i : in std_logic_vector(XIRQ_NUM_CH-1 downto 0) := (others => '0'); -- IRQ channels
-- CPU Interrupts --
msw_irq_i : in std_logic := '0'; -- machine software interrupt
mext_irq_i : in std_logic := '0' -- machine external interrupt
);
end entity;
architecture neorv32_SystemTop_axi4lite_rtl of neorv32_SystemTop_axi4lite is
-- type conversion --
constant IO_CFS_CONFIG_INT : std_ulogic_vector(31 downto 0) := std_ulogic_vector(IO_CFS_CONFIG);
constant XIRQ_TRIGGER_TYPE_INT : std_ulogic_vector(31 downto 0) := std_ulogic_vector(XIRQ_TRIGGER_TYPE);
constant XIRQ_TRIGGER_POLARITY_INT : std_ulogic_vector(31 downto 0) := std_ulogic_vector(XIRQ_TRIGGER_POLARITY);
--
signal clk_i_int : std_ulogic;
signal rstn_i_int : std_ulogic;
--
signal jtag_trst_i_int :std_ulogic;
signal jtag_tck_i_int :std_ulogic;
signal jtag_tdi_i_int :std_ulogic;
signal jtag_tdo_o_int :std_ulogic;
signal jtag_tms_i_int :std_ulogic;
--
signal gpio_o_int : std_ulogic_vector(63 downto 0);
signal gpio_i_int : std_ulogic_vector(63 downto 0);
--
signal uart0_txd_o_int : std_ulogic;
signal uart0_rxd_i_int : std_ulogic;
signal uart0_rts_o_int : std_ulogic;
signal uart0_cts_i_int : std_ulogic;
--
signal uart1_txd_o_int : std_ulogic;
signal uart1_rxd_i_int : std_ulogic;
signal uart1_rts_o_int : std_ulogic;
signal uart1_cts_i_int : std_ulogic;
--
signal spi_sck_o_int : std_ulogic;
signal spi_sdo_o_int : std_ulogic;
signal spi_sdi_i_int : std_ulogic;
signal spi_csn_o_int : std_ulogic_vector(07 downto 0);
--
signal pwm_o_int : std_ulogic_vector(IO_PWM_NUM_CH-1 downto 0);
--
signal cfs_in_i_int : std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0);
signal cfs_out_o_int : std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0);
--
signal neoled_o_int : std_ulogic;
--
signal xirq_i_int : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
--
signal msw_irq_i_int : std_ulogic;
signal mext_irq_i_int : std_ulogic;
-- internal wishbone bus --
type wb_bus_t is record
adr : std_ulogic_vector(31 downto 0); -- address
di : std_ulogic_vector(31 downto 0); -- processor input data
do : std_ulogic_vector(31 downto 0); -- processor output data
we : std_ulogic; -- write enable
sel : std_ulogic_vector(03 downto 0); -- byte enable
stb : std_ulogic; -- strobe
cyc : std_ulogic; -- valid cycle
ack : std_ulogic; -- transfer acknowledge
err : std_ulogic; -- transfer error
tag : std_ulogic_vector(02 downto 0); -- tag
lock : std_ulogic; -- exclusive access request
end record;
signal wb_core : wb_bus_t;
-- AXI bridge control --
type ctrl_t is record
radr_received : std_ulogic;
wadr_received : std_ulogic;
wdat_received : std_ulogic;
end record;
signal ctrl : ctrl_t;
signal ack_read, ack_write : std_ulogic; -- normal transfer termination
signal err_read, err_write : std_ulogic; -- error transfer termination
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (CPU_EXTENSION_RISCV_A = true) report "NEORV32 PROCESSOR CONFIG WARNING: AXI4-Lite provides NO support for atomic memory operations. LR/SC access via AXI will raise a bus exception." severity warning;
-- The Core Of The Problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_top_inst: neorv32_top
generic map (
-- General --
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN => INT_BOOTLOADER_EN, -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id (hartid)
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN => ON_CHIP_DEBUGGER_EN, -- implement on-chip debugger
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr, -- implement base counters?
CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm, -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
-- Extension Options --
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH, -- total size of HPM counters (0..64)
-- Internal Instruction memory --
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, -- size of processor-internal data memory in bytes
-- Internal Cache memory --
ICACHE_EN => ICACHE_EN, -- implement instruction cache
ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY => ICACHE_ASSOCIATIVITY, -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
-- External memory interface --
MEM_EXT_EN => true, -- implement external memory bus interface?
MEM_EXT_TIMEOUT => 0, -- cycles after a pending bus access auto-terminates (0 = disabled)
MEM_EXT_PIPE_MODE => false, -- protocol: false=classic/standard wishbone mode, true=pipelined wishbone mode
MEM_EXT_BIG_ENDIAN => false, -- byte order: true=big-endian, false=little-endian
MEM_EXT_ASYNC_RX => false, -- use register buffer for RX data when false
-- External Interrupts Controller (XIRQ) --
XIRQ_NUM_CH => XIRQ_NUM_CH, -- number of external IRQ channels (0..32)
XIRQ_TRIGGER_TYPE => XIRQ_TRIGGER_TYPE_INT, -- trigger type: 0=level, 1=edge
XIRQ_TRIGGER_POLARITY => XIRQ_TRIGGER_POLARITY_INT, -- trigger polarity: 0=low-level/falling-edge, 1=high-level/rising-edge
-- Processor peripherals --
IO_GPIO_EN => IO_GPIO_EN, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => IO_MTIME_EN, -- implement machine system timer (MTIME)?
IO_UART0_EN => IO_UART0_EN, -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO => IO_UART0_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO => IO_UART0_TX_FIFO, -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN => IO_UART1_EN, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO => IO_UART1_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO => IO_UART1_TX_FIFO, -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN => IO_SPI_EN, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => IO_TWI_EN, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => IO_PWM_NUM_CH, -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN => IO_WDT_EN, -- implement watch dog timer (WDT)?
IO_TRNG_EN => IO_TRNG_EN, -- implement true random number generator (TRNG)?
IO_CFS_EN => IO_CFS_EN, -- implement custom functions subsystem (CFS)?
IO_CFS_CONFIG => IO_CFS_CONFIG_INT, -- custom CFS configuration generic
IO_CFS_IN_SIZE => IO_CFS_IN_SIZE, -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE => IO_CFS_OUT_SIZE, -- size of CFS output conduit in bits
IO_NEOLED_EN => IO_NEOLED_EN, -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_TX_FIFO => IO_NEOLED_TX_FIFO, -- NEOLED TX FIFO depth, 1..32k, has to be a power of two
IO_GPTMR_EN => IO_GPTMR_EN -- implement general purpose timer (GPTMR)?
)
port map (
-- Global control --
clk_i => clk_i_int, -- global clock, rising edge
rstn_i => rstn_i_int, -- global reset, low-active, async
-- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) --
jtag_trst_i => jtag_trst_i_int, -- low-active TAP reset (optional)
jtag_tck_i => jtag_tck_i_int, -- serial clock
jtag_tdi_i => jtag_tdi_i_int, -- serial data input
jtag_tdo_o => jtag_tdo_o_int, -- serial data output
jtag_tms_i => jtag_tms_i_int, -- mode select
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
wb_tag_o => wb_core.tag, -- tag
wb_adr_o => wb_core.adr, -- address
wb_dat_i => wb_core.di, -- read data
wb_dat_o => wb_core.do, -- write data
wb_we_o => wb_core.we, -- read/write
wb_sel_o => wb_core.sel, -- byte enable
wb_stb_o => wb_core.stb, -- strobe
wb_cyc_o => wb_core.cyc, -- valid cycle
wb_lock_o => wb_core.lock, -- exclusive access request
wb_ack_i => wb_core.ack, -- transfer acknowledge
wb_err_i => wb_core.err, -- transfer error
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => open, -- indicates an executed FENCE operation
fencei_o => open, -- indicates an executed FENCEI operation
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o => gpio_o_int, -- parallel output
gpio_i => gpio_i_int, -- parallel input
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o => uart0_txd_o_int, -- UART0 send data
uart0_rxd_i => uart0_rxd_i_int, -- UART0 receive data
uart0_rts_o => uart0_rts_o_int, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_cts_i => uart0_cts_i_int, -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o => uart1_txd_o_int, -- UART1 send data
uart1_rxd_i => uart1_rxd_i_int, -- UART1 receive data
uart1_rts_o => uart1_rts_o_int, -- hw flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_cts_i => uart1_cts_i_int, -- hw flow control: UART1.TX allowed to transmit, low-active, optional
-- SPI (available if IO_SPI_EN = true) --
spi_sck_o => spi_sck_o_int, -- SPI serial clock
spi_sdo_o => spi_sdo_o_int, -- controller data out, peripheral data in
spi_sdi_i => spi_sdi_i_int, -- controller data in, peripheral data out
spi_csn_o => spi_csn_o_int, -- SPI CS
-- TWI (available if IO_TWI_EN = true) --
twi_sda_io => twi_sda_io, -- twi serial data line
twi_scl_io => twi_scl_io, -- twi serial clock line
-- PWM available if IO_PWM_NUM_CH > 0) --
pwm_o => pwm_o_int, -- pwm channels
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) --
cfs_in_i => cfs_in_i_int, -- custom inputs
cfs_out_o => cfs_out_o_int, -- custom outputs
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o => neoled_o_int, -- async serial data line
-- System time --
mtime_i => (others => '0'), -- current system time from ext. MTIME (if IO_MTIME_EN = false)
mtime_o => open, -- current system time from int. MTIME (if IO_MTIME_EN = true)
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
xirq_i => xirq_i_int, -- IRQ channels
-- CPU Interrupts --
mtime_irq_i => '0', -- machine timer interrupt, available if IO_MTIME_EN = false
msw_irq_i => msw_irq_i_int, -- machine software interrupt
mext_irq_i => mext_irq_i_int -- machine external interrupt
);
-- type conversion --
gpio_o <= std_logic_vector(gpio_o_int);
gpio_i_int <= std_ulogic_vector(gpio_i);
jtag_trst_i_int <= std_ulogic(jtag_trst_i);
jtag_tck_i_int <= std_ulogic(jtag_tck_i);
jtag_tdi_i_int <= std_ulogic(jtag_tdi_i);
jtag_tdo_o <= std_logic(jtag_tdo_o_int);
jtag_tms_i_int <= std_ulogic(jtag_tms_i);
uart0_txd_o <= std_logic(uart0_txd_o_int);
uart0_rxd_i_int <= std_ulogic(uart0_rxd_i);
uart0_rts_o <= std_logic(uart0_rts_o_int);
uart0_cts_i_int <= std_ulogic(uart0_cts_i);
uart1_txd_o <= std_logic(uart1_txd_o_int);
uart1_rxd_i_int <= std_ulogic(uart1_rxd_i);
uart1_rts_o <= std_logic(uart1_rts_o_int);
uart1_cts_i_int <= std_ulogic(uart1_cts_i);
spi_sck_o <= std_logic(spi_sck_o_int);
spi_sdo_o <= std_logic(spi_sdo_o_int);
spi_sdi_i_int <= std_ulogic(spi_sdi_i);
spi_csn_o <= std_logic_vector(spi_csn_o_int);
pwm_o <= std_logic_vector(pwm_o_int);
cfs_in_i_int <= std_ulogic_vector(cfs_in_i);
cfs_out_o <= std_logic_vector(cfs_out_o_int);
neoled_o <= std_logic(neoled_o_int);
xirq_i_int <= std_ulogic_vector(xirq_i);
msw_irq_i_int <= std_ulogic(msw_irq_i);
mext_irq_i_int <= std_ulogic(mext_irq_i);
-- Wishbone to AXI4-Lite Bridge -----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- access arbiter --
axi_access_arbiter: process(rstn_i_int, clk_i_int)
begin
if (rstn_i_int = '0') then
ctrl.radr_received <= '0';
ctrl.wadr_received <= '0';
ctrl.wdat_received <= '0';
elsif rising_edge(clk_i_int) then
if (wb_core.cyc = '0') then -- idle
ctrl.radr_received <= '0';
ctrl.wadr_received <= '0';
ctrl.wdat_received <= '0';
else -- busy
-- "read address received" flag --
if (wb_core.we = '0') then -- pending READ
if (m_axi_arready = '1') then -- read address received by interconnect?
ctrl.radr_received <= '1';
end if;
end if;
-- "write address received" flag --
if (wb_core.we = '1') then -- pending WRITE
if (m_axi_awready = '1') then -- write address received by interconnect?
ctrl.wadr_received <= '1';
end if;
end if;
-- "write data received" flag --
if (wb_core.we = '1') then -- pending WRITE
if (m_axi_wready = '1') then -- write data received by interconnect?
ctrl.wdat_received <= '1';
end if;
end if;
end if;
end if;
end process axi_access_arbiter;
-- AXI4-Lite Global Signals --
clk_i_int <= std_ulogic(m_axi_aclk);
rstn_i_int <= std_ulogic(m_axi_aresetn);
-- AXI4-Lite Read Address Channel --
m_axi_araddr <= std_logic_vector(wb_core.adr);
m_axi_arvalid <= std_logic((wb_core.cyc and (not wb_core.we)) and (not ctrl.radr_received));
--m_axi_arprot <= "000"; -- recommended by Xilinx
m_axi_arprot(0) <= wb_core.tag(0); -- 0:unprivileged access, 1:privileged access
m_axi_arprot(1) <= wb_core.tag(1); -- 0:secure access, 1:non-secure access
m_axi_arprot(2) <= wb_core.tag(2); -- 0:data access, 1:instruction access
-- AXI4-Lite Read Data Channel --
m_axi_rready <= std_logic(wb_core.cyc and (not wb_core.we));
wb_core.di <= std_ulogic_vector(m_axi_rdata);
ack_read <= std_ulogic(m_axi_rvalid);
err_read <= '0' when (m_axi_rresp = "00") else '1'; -- read response = ok? check this signal only when m_axi_rvalid = '1'
-- AXI4-Lite Write Address Channel --
m_axi_awaddr <= std_logic_vector(wb_core.adr);
m_axi_awvalid <= std_logic((wb_core.cyc and wb_core.we) and (not ctrl.wadr_received));
--m_axi_awprot <= "000"; -- recommended by Xilinx
m_axi_awprot(0) <= wb_core.tag(0); -- 0:unprivileged access, 1:privileged access
m_axi_awprot(1) <= wb_core.tag(1); -- 0:secure access, 1:non-secure access
m_axi_awprot(2) <= wb_core.tag(2); -- 0:data access, 1:instruction access
-- AXI4-Lite Write Data Channel --
m_axi_wdata <= std_logic_vector(wb_core.do);
m_axi_wvalid <= std_logic((wb_core.cyc and wb_core.we) and (not ctrl.wdat_received));
m_axi_wstrb <= std_logic_vector(wb_core.sel); -- byte-enable
-- AXI4-Lite Write Response Channel --
m_axi_bready <= std_logic(wb_core.cyc and wb_core.we);
ack_write <= std_ulogic(m_axi_bvalid);
err_write <= '0' when (m_axi_bresp = "00") else '1'; -- write response = ok? check this signal only when m_axi_bvalid = '1'
-- Wishbone transfer termination --
wb_core.ack <= ack_read or ack_write;
wb_core.err <= (ack_read and err_read) or (ack_write and err_write) or wb_core.lock;
end architecture;

View File

@ -0,0 +1,52 @@
# Test Setups
This folder contains very simple test setups that are intended for project beginners
to setup a minimal NEORV32 SoC. These setups are used in the :books:
[NEORV32 User Guide](https://stnolting.github.io/neorv32/ug/).
Note that these setups provides a minimalistic configuration to keep
things at a simple level at first. Additional CPU ISA extensions, performance options and
optional peripheral modules can be enabled by specifying the according :book:
[configuration generics](https://stnolting.github.io/neorv32/#_processor_top_entity_generics).
### Setup's Top Entity
#### Clocking and Reset
All test setups require an external clock (via `clk_i` signal) and an external
low-active reset (via `rstn_i` signal).
#### Configuration Generics
Each setup provides three elementary generics that can/should be adapted to fit
your FPGA/board.
* The clock speed in Hz **has to be specified** via the `CLOCK_SPEED` generic to fit your clock source.
* The processor-internal instruction memory (IMEM) size _can be modified_ via the `MEM_INT_IMEM_SIZE` generic.
* The processor-internal data memory (DMEM) size _can be modified_ via the `MEM_INT_DMEM_SIZE` generic.
Note that this might require adaption of the NEORV32 linker script.
### [`neorv32_test_setup_approm.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/test_setups/neorv32_test_setup_approm.vhd)
This setup configures a `rv32imc_Zicsr` CPU with 16kB IMEM (as pre-initialized ROM),
8kB DMEM and includes the GPIO module to drive 8 external signals (`gpio_o`)
and the MTIME module for generating timer interrupts.
The setup uses the ["indirect boot"](https://stnolting.github.io/neorv32/#_indirect_boot)
configuration, so software applications are "installed" directly into the
processor-internal IMEM during synthesis.
:books: See User Guide section [_Installing an Executable Directly Into Memory_](https://stnolting.github.io/neorv32/ug/#_installing_an_executable_directly_into_memory).
### [`neorv32_test_setup_bootloader.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/test_setups/neorv32_test_setup_bootloader.vhd)
This setup configures a `rv32imc_Zicsr` CPU with 16kB IMEM (as RAM), 8kB DMEM
and includes the GPIO module to drive 8 external signals (`gpio_o`), the MTIME
module for generating timer interrupts and UART0 to interface with the bootloader
(via `uart0_txd_o` and `uart0_rxd_i`) via a serial terminal.
The setup uses the ["direct boot"](https://stnolting.github.io/neorv32/#_direct_boot)
configuration, so software applications can be uploaded and run at any timer via a serial terminal.
:books: See User Guide section
[_Uploading and Starting of a Binary Executable Image via UART_](https://stnolting.github.io/neorv32/ug/#_uploading_and_starting_of_a_binary_executable_image_via_uart).

View File

@ -0,0 +1,98 @@
-- #################################################################################################
-- # << NEORV32 - Test Setup using the internal IMEM as ROM to run pre-installed executables >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
-- # #
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
-- # conditions and the following disclaimer. #
-- # #
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
-- # conditions and the following disclaimer in the documentation and/or other materials #
-- # provided with the distribution. #
-- # #
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
-- # endorse or promote products derived from this software without specific prior written #
-- # permission. #
-- # #
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
-- # ********************************************************************************************* #
-- # The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library neorv32;
use neorv32.neorv32_package.all;
entity neorv32_test_setup_approm is
generic (
-- adapt these for your setup --
CLOCK_FREQUENCY : natural := 100000000; -- clock frequency of clk_i in Hz
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes
MEM_INT_DMEM_SIZE : natural := 8*1024 -- size of processor-internal data memory in bytes
);
port (
-- Global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
-- GPIO --
gpio_o : out std_ulogic_vector(7 downto 0) -- parallel output
);
end entity;
architecture neorv32_test_setup_approm_rtl of neorv32_test_setup_approm is
signal con_gpio_o : std_ulogic_vector(63 downto 0);
begin
-- The Core Of The Problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_top_inst: neorv32_top
generic map (
-- General --
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN => false, -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C => true, -- implement compressed extension?
CPU_EXTENSION_RISCV_M => true, -- implement mul/div extension?
CPU_EXTENSION_RISCV_Zicsr => true, -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr => true, -- implement base counters?
-- Internal Instruction memory --
MEM_INT_IMEM_EN => true, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN => true, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, -- size of processor-internal data memory in bytes
-- Processor peripherals --
IO_GPIO_EN => true, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => true -- implement machine system timer (MTIME)?
)
port map (
-- Global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o => con_gpio_o -- parallel output
);
-- GPIO output --
gpio_o <= con_gpio_o(7 downto 0);
end architecture;

View File

@ -0,0 +1,105 @@
-- #################################################################################################
-- # << NEORV32 - Test Setup using the UART-Bootloader to upload and run executables >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
-- # #
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
-- # conditions and the following disclaimer. #
-- # #
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
-- # conditions and the following disclaimer in the documentation and/or other materials #
-- # provided with the distribution. #
-- # #
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
-- # endorse or promote products derived from this software without specific prior written #
-- # permission. #
-- # #
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
-- # ********************************************************************************************* #
-- # The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library neorv32;
use neorv32.neorv32_package.all;
entity neorv32_test_setup_bootloader is
generic (
-- adapt these for your setup --
CLOCK_FREQUENCY : natural := 100000000; -- clock frequency of clk_i in Hz
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes
MEM_INT_DMEM_SIZE : natural := 8*1024 -- size of processor-internal data memory in bytes
);
port (
-- Global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
-- GPIO --
gpio_o : out std_ulogic_vector(7 downto 0); -- parallel output
-- UART0 --
uart0_txd_o : out std_ulogic; -- UART0 send data
uart0_rxd_i : in std_ulogic -- UART0 receive data
);
end entity;
architecture neorv32_test_setup_bootloader_rtl of neorv32_test_setup_bootloader is
signal con_gpio_o : std_ulogic_vector(63 downto 0);
begin
-- The Core Of The Problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_top_inst: neorv32_top
generic map (
-- General --
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN => true, -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_C => true, -- implement compressed extension?
CPU_EXTENSION_RISCV_M => true, -- implement mul/div extension?
CPU_EXTENSION_RISCV_Zicsr => true, -- implement CSR system?
CPU_EXTENSION_RISCV_Zicntr => true, -- implement base counters?
-- Internal Instruction memory --
MEM_INT_IMEM_EN => true, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes
-- Internal Data memory --
MEM_INT_DMEM_EN => true, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, -- size of processor-internal data memory in bytes
-- Processor peripherals --
IO_GPIO_EN => true, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => true, -- implement machine system timer (MTIME)?
IO_UART0_EN => true -- implement primary universal asynchronous receiver/transmitter (UART0)?
)
port map (
-- Global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o => con_gpio_o, -- parallel output
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o => uart0_txd_o, -- UART0 send data
uart0_rxd_i => uart0_rxd_i -- UART0 receive data
);
-- GPIO output --
gpio_o <= con_gpio_o(7 downto 0);
end architecture;

View File

@ -0,0 +1,65 @@
# Exemplary FPGA Board Setups
* [Setups using Commercial Toolchains](#Setups-using-Commercial-Toolchains)
* [Setups using Open-Source Toolchains](#Setups-using-Open-Source-Toolchains)
* [Adding Your Project Setup](#Adding-Your-Project-Setup)
* [Setup-Specific NEORV32 Software Framework Modification](#Setup-Specific-NEORV32-Software-Framework-Modification)
This folder provides exemplary NEORV32 SoC setups and projects for different FPGA platforms/boards.
You can directly use one of the provided setups or use them as starting point to build your own setup.
Project maintainers may make pull requests against this repository to [add or link their setups](#Adding-Your-Project-Setup).
## Setups using Commercial Toolchains
| Setup | Toolchain | Board :books: | FPGA | Author(s) |
|:------|:----------|:--------------|:------|:----------|
| :file_folder: [`de0-nano-test-setup`](https://github.com/stnolting/neorv32/tree/master/setups/quartus/de0-nano-test-setup) | Intel Quartus Prime | [Terasic DE0-Nano](https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=139&No=593) | Intel Cyclone IV `EP4CE22F17C6N` | [stnolting](https://github.com/stnolting) |
| :file_folder: [`de0-nano-test-setup-qsys`](quartus/de0-nano-test-setup-qsys) | Intel Quartus Prime | [Terasic DE0-Nano](https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=139&No=593) | Intel Cyclone IV `EP4CE22F17C6N` | [torerams](https://github.com/torerams) |
| :file_folder: [`de0-nano-test-setup-avalonmm`](quartus/de0-nano-test-setup-avalonmm-wrapper) | Intel Quartus Prime | [Terasic DE0-Nano](https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=139&No=593) | Intel Cyclone IV `EP4CE22F17C6N` | [torerams](https://github.com/torerams) |
| :file_folder: [`terasic-cyclone-V-gx-starter-kit-test-setup`](https://github.com/stnolting/neorv32/tree/master/setups/quartus/terasic-cyclone-V-gx-starter-kit-test-setup) | Intel Quartus Prime | [Terasic Cyclone-V GX Starter Kit](https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=167&No=830) | Intel Cyclone V `5CGXFC5C6F27C7N` | zs6mue |
| :file_folder: [`UPduino_v3`](https://github.com/stnolting/neorv32/tree/master/setups/radiant/UPduino_v3) | Lattice Radiant | [tinyVision.ai Inc. UPduino `v3.0`](https://www.tindie.com/products/tinyvision_ai/upduino-v30-low-cost-lattice-ice40-fpga-board/) | Lattice iCE40 UltraPlus `iCE40UP5K-SG48I` | [stnolting](https://github.com/stnolting) |
| :file_folder: [`arty-a7-35-test-setup`](https://github.com/stnolting/neorv32/tree/master/setups/vivado/arty-a7-test-setup) | Xilinx Vivado | [Digilent Arty A7-35](https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start) | Xilinx Artix-7 `XC7A35TICSG324-1L` | [stnolting](https://github.com/stnolting) |
| :file_folder: [`nexys-a7-test-setup`](https://github.com/stnolting/neorv32/tree/master/setups/vivado/nexys-a7-test-setup) | Xilinx Vivado | [Digilent Nexys A7](https://reference.digilentinc.com/reference/programmable-logic/nexys-a7/start) | Xilinx Artix-7 `XC7A50TCSG324-1` | [AWenzel83](https://github.com/AWenzel83) |
| :file_folder: [`nexys-a7-test-setup`](https://github.com/stnolting/neorv32/tree/master/setups/vivado/nexys-a7-test-setup) | Xilinx Vivado | [Digilent Nexys 4 DDR](https://reference.digilentinc.com/reference/programmable-logic/nexys-4-ddr/start) | Xilinx Artix-7 `XC7A100TCSG324-1` | [AWenzel83](https://github.com/AWenzel83) |
| :earth_africa: [custom CRC32 processor module for the nexys-a7 boards (**tutorial**)](https://github.com/motius/neorv32/tree/add-custom-crc32-module) | Xilinx Vivado | [Digilent Nexys A7](https://reference.digilentinc.com/reference/programmable-logic/nexys-a7/start) | Xilinx Artix-7 `XC7A50TCSG324-1` | [motius](https://github.com/motius) ([ikstvn](https://github.com/ikstvn), [turbinenreiter](https://github.com/turbinenreiter)) |
| :earth_africa: [neorv32-examples](https://github.com/emb4fun/neorv32-examples) | Intel Quartus Prime | Different Terasic boards | Different Intel FPGAs | [emb4fun](https://github.com/emb4fun) |
## Setups using Open-Source Toolchains
| Setup | Toolchain | Board :books: | FPGA | Author(s) |
|:------|:----------|:--------------|:------|:----------|
| :file_folder: [`UPduino v3`](https://github.com/stnolting/neorv32/tree/master/setups/osflow) | GHDL, Yosys, nextPNR | [UPduino v3.0](https://www.tindie.com/products/tinyvision_ai/upduino-v30-low-cost-lattice-ice40-fpga-board/) | Lattice iCE40 UltraPlus `iCE40UP5K-SG48I` | [tmeissner](https://github.com/tmeissner) |
| :file_folder: [`FOMU`](https://github.com/stnolting/neorv32/tree/master/setups/osflow) | GHDL, Yosys, nextPNR | [FOMU](https://tomu.im/fomu.html) | Lattice iCE40 UltraPlus `iCE40UP5K-SG48I` | [umarcor](https://github.com/umarcor) |
| :file_folder: [`iCESugar`](https://github.com/stnolting/neorv32/tree/master/setups/osflow) | GHDL, Yosys, nextPNR | [iCESugar](https://github.com/wuxx/icesugar/blob/master/README_en.md) | Lattice iCE40 UltraPlus `iCE40UP5K-SG48I` | [umarcor](https://github.com/umarcor) |
| :file_folder: [`AlhambraII`](https://github.com/stnolting/neorv32/tree/master/setups/osflow) | GHDL, Yosys, nextPNR | [AlhambraII](https://alhambrabits.com/alhambra/) | Lattice iCE40HX4K | [zipotron](https://github.com/zipotron) |
| :file_folder: [`Orange Crab`](https://github.com/stnolting/neorv32/tree/master/setups/osflow) | GHDL, Yosys, nextPNR | [Orange Crab](https://github.com/gregdavill/OrangeCrab) | Lattice ECP5-25F | [umarcor](https://github.com/umarcor), [jeremyherbert](https://github.com/jeremyherbert) |
| :file_folder: [`ULX3S`](https://github.com/stnolting/neorv32/tree/master/setups/osflow) | GHDL, Yosys, nextPNR | [ULX3S](https://radiona.org/ulx3s/) | Lattice ECP5 `LFE5U-85F-6BG381C` | [zipotron](https://github.com/zipotron) |
| :earth_africa: [`ULX3S-SDRAM`](https://github.com/zipotron/neorv32-complex-setups) | GHDL, Yosys, nextPNR | [ULX3S](https://radiona.org/ulx3s/) | Lattice ECP5 `LFE5U-85F-6BG381C` | [zipotron](https://github.com/zipotron) |
:information_source: All setups using open-source toolchains are located in the
[`osflow`](https://github.com/stnolting/neorv32/tree/master/setups/osflow) folder.
See the README there for more information how to run a specific setup / configuration.
## Adding Your Project Setup
Please respect the following guidelines if you'd like to add (or link) your setup to the list.
* check out the project's [code of conduct](https://github.com/stnolting/neorv32/tree/master/CODE_OF_CONDUCT.md)
* add a link if the board you are using provides online documentation (and/or can be purchased somewhere)
* use the :file_folder: emoji (`:file_folder:`) if the setup is located *in this* folder; use the :earth_africa:
emoji (`:earth_africa:`) if it is a link to your local project
* please add a `README` to give some brief information about the setup and a `.gitignore` to keep things clean;
take a look at [`UPduino_v3`](https://github.com/stnolting/neorv32/tree/master/setups/radiant/UPduino_v3) to get some ideas what a project setup might look like
## Setup-Specific NEORV32 Software Framework Modification
In order to use the features provided by the setups, minor *optional* changes can be made to the default NEORV32 setup.
* To change the default data memory size take a look at the :books: User Guide section
[_General Software Framework Setup_](https://stnolting.github.io/neorv32/ug/#_general_software_framework_setup)
* To modify the SPI flash base address for storing/booting software application see :books: User Guide section
[_Customizing the Internal Bootloader_](https://stnolting.github.io/neorv32/ug/#_customizing_the_internal_bootloader)

View File

@ -0,0 +1,8 @@
*.asc
*.bit
*.cfg
*.dfu
*.history
*.json
*.svf
*-report.txt

View File

@ -0,0 +1,134 @@
TEMPLATES := ../../rtl/processor_templates
MV := mv
.DEFAULT_GOAL := help
TASK := clean $(BITSTREAM)
FOMU_REV ?= pvt
OrangeCrab_REV ?= r02-25F
UPduino_REV ?= v3
#ifndef BOARD
#$(error BOARD needs to be set to 'Fomu', 'iCESugar', 'UPDuino', 'iCEBreaker' or 'OrangeCrab' !)
#endif
run:
$(eval TASK ?= clean $(BITSTREAM))
$(MAKE) -f common.mk \
BOARD_SRC=./board_tops/neorv32_$(BOARD)_BoardTop_$(DESIGN).vhd \
TOP=neorv32_$(BOARD)_BoardTop_$(DESIGN) \
ID=$(DESIGN) \
$(TASK)
IMPL="$${BITSTREAM%%.*}"; for item in ".bit" ".svf"; do \
if [ -f "./$$IMPL$$item" ]; then \
$(MV) "./$$IMPL$$item" ./; \
fi \
done
# Boards
Fomu:
$(eval BITSTREAM ?= neorv32_$(BOARD)_$(FOMU_REV)_$(DESIGN).bit)
ifeq ($(DESIGN),Minimal)
$(eval IMEM_SRC := ../../rtl/core/mem/neorv32_imem.default.vhd)
else
$(eval IMEM_SRC := devices/ice40/neorv32_imem.ice40up_spram.vhd)
endif
$(eval NEORV32_MEM_SRC ?= ${IMEM_SRC} devices/ice40/neorv32_dmem.ice40up_spram.vhd)
$(MAKE) \
BITSTREAM="$(BITSTREAM)" \
NEORV32_MEM_SRC="$(NEORV32_MEM_SRC)" \
run
iCESugar:
$(eval BITSTREAM ?= neorv32_$(BOARD)_$(DESIGN).bit)
$(eval NEORV32_MEM_SRC ?= devices/ice40/neorv32_imem.ice40up_spram.vhd devices/ice40/neorv32_dmem.ice40up_spram.vhd)
$(MAKE) \
BITSTREAM="$(BITSTREAM)" \
NEORV32_MEM_SRC="$(NEORV32_MEM_SRC)" \
run
UPduino:
$(eval BITSTREAM ?= neorv32_$(BOARD)_$(UPduino_REV)_$(DESIGN).bit)
$(eval NEORV32_MEM_SRC ?= devices/ice40/neorv32_imem.ice40up_spram.vhd devices/ice40/neorv32_dmem.ice40up_spram.vhd)
$(MAKE) \
BITSTREAM="$(BITSTREAM)" \
NEORV32_MEM_SRC="$(NEORV32_MEM_SRC)" \
run
OrangeCrab:
$(eval BITSTREAM ?= neorv32_$(BOARD)_$(OrangeCrab_REV)_$(DESIGN).bit)
$(eval NEORV32_MEM_SRC ?= ../../rtl/core/mem/neorv32_imem.default.vhd ../../rtl/core/mem/neorv32_dmem.default.vhd)
$(MAKE) \
BITSTREAM="$(BITSTREAM)" \
NEORV32_MEM_SRC="$(NEORV32_MEM_SRC)" \
run
AlhambraII:
$(eval BITSTREAM ?= neorv32_$(BOARD)_$(DESIGN).bit)
$(eval NEORV32_MEM_SRC ?= ../../rtl/core/mem/neorv32_imem.default.vhd ../../rtl/core/mem/neorv32_dmem.default.vhd)
$(MAKE) \
BITSTREAM="$(BITSTREAM)" \
NEORV32_MEM_SRC="$(NEORV32_MEM_SRC)" \
run
ULX3S:
$(eval BITSTREAM ?= neorv32_$(BOARD)_$(DESIGN).bit)
$(eval NEORV32_MEM_SRC ?= ../../rtl/core/mem/neorv32_imem.default.vhd ../../rtl/core/mem/neorv32_dmem.default.vhd)
$(MAKE) \
BITSTREAM="$(BITSTREAM)" \
NEORV32_MEM_SRC="$(NEORV32_MEM_SRC)" \
run
iCEBreaker:
$(eval BITSTREAM ?= neorv32_$(BOARD)_$(DESIGN).bit)
$(eval NEORV32_MEM_SRC ?= devices/ice40/neorv32_imem.ice40up_spram.vhd devices/ice40/neorv32_dmem.ice40up_spram.vhd)
$(MAKE) \
BITSTREAM="$(BITSTREAM)" \
NEORV32_MEM_SRC="$(NEORV32_MEM_SRC)" \
run
# Designs
Minimal:
$(eval DESIGN ?= $@)
$(eval DESIGN_SRC ?= $(TEMPLATES)/neorv32_ProcessorTop_Minimal*.vhd)
$(MAKE) \
DESIGN="$(DESIGN)" \
DESIGN_SRC="$(DESIGN_SRC)" \
$(BOARD)
MinimalBoot:
$(eval DESIGN ?= $@)
$(eval DESIGN_SRC ?= $(TEMPLATES)/neorv32_ProcessorTop_MinimalBoot.vhd)
$(MAKE) \
DESIGN="$(DESIGN)" \
DESIGN_SRC="$(DESIGN_SRC)" \
$(BOARD)
UP5KDemo:
$(eval DESIGN ?= $@)
$(eval DESIGN_SRC ?= $(TEMPLATES)/neorv32_ProcessorTop_UP5KDemo.vhd)
$(MAKE) \
DESIGN="$(DESIGN)" \
DESIGN_SRC="$(DESIGN_SRC)" \
$(BOARD)
MixedLanguage:
$(eval DESIGN ?= $@)
$(eval DESIGN_SRC ?= $(TEMPLATES)/neorv32_ProcessorTop_Minimal*.vhd)
$(eval NEORV32_VERILOG_SRC ?= devices/ice40/sb_ice40_components.v board_tops/neorv32_Fomu_MixedLanguage_ClkGen.v)
$(MAKE) \
DESIGN="$(DESIGN)" \
DESIGN_SRC="$(DESIGN_SRC)" \
NEORV32_VERILOG_SRC="$(NEORV32_VERILOG_SRC)" \
$(BOARD)
# Help
help:
@echo "Open-Source Synthesis, P&R, Routing and Bitstream Generation"
@echo "Usage: make BOARD=<fpga board> <board top>"
@echo "Example: make BOARD=Fomu Minimal"

View File

@ -0,0 +1,14 @@
${IMPL}.${PNR2BIT_EXT}: $(IMPL).json $(CONSTRAINTS)
$(NEXTPNR) \
$(PNRFLAGS) \
--$(CONSTRAINTS_FORMAT) $(CONSTRAINTS) \
--json $(IMPL).json \
--${NEXTPNR_OUT} $@ 2>&1 | tee nextpnr-report.txt
${IMPL}.bit: ${IMPL}.${PNR2BIT_EXT}
$(PACKTOOL) $< $@
ifeq ($(DEVICE_SERIES),ecp5)
${IMPL}.svf: ${IMPL}.${PNR2BIT_EXT}
$(PACKTOOL) $(PACKARGS) --svf $@ $<
endif

View File

@ -0,0 +1,145 @@
# Exemplary FPAG Board Setups - Using Open Source Toolchains
* [Folder Structure](#Folder-Structure)
* [Prerequisites](#Prerequisites)
* [How To Run](#How-To-Run)
* [Porting to a new FPGA or Board](#Porting-to-a-new-FPGA-or-Board)
This folder provides the infrastructure for generating bitstream for various FPGAs using
open-source toolchains. Synthesis is based on [ghdl-yosys](https://github.com/ghdl/ghdl-yosys-plugin).
:information_source: Note that the provided setups just implement very basic SoC configurations.
These setups are intended as minimal example (how to synthesize the processor) for a given FPGA + board
that can be used as starting point to build more complex user-defined SoCs.
## Folder Structure
* `.`: Main makefile (main entry point) and partial-makefiles for synthesis, place & route and bitstream generation
* `boards`: board-specific _partial makefiles_ (used by main makefile "`Makefile`") for generating bitstreams
* `board_top`: board-specific top entities (board wrappers; may include FPGA-specific modules)
* `constraints`: physical constraints (mainly pin mappings)
* `devices`: FPGA-specific primitives and optimized processor modules (like memories)
## Prerequisites
:construction: TODO :construction:
* local installation of the tools
* using containers
## How To Run
:construction: TODO :construction:
The `Makefile` in this folder is the main entry point. To run the whole process of synthesis, place & route and bitstream
generation run:
**Prototype:**
```
make BOARD=<FPGA_board> <System_Top_HDL>
```
**Example:**
```
make BOARD=Fomu Minimal
```
`<FPGA_board>` specifies the actual FPGA board and implicitly sets the FPGA type. The currently supported FPGA board
targets are listed in the `boards/` folder where each partial-makefile corresponds to a supported platform.
`<System_Top_HDL>` is used to define the actual SoC top. Available SoCs are located in
[`rtl/processor_templates`](https://github.com/stnolting/neorv32/tree/master/rtl/processor_templates).
## Porting to a new FPGA or Board
This sections illustrates how to add a new basic setup for a specific FPGA and board. This tutorial used the iCEBreaker
"MinimalBoot" setup as reference.
#### 1. Setup a board- and FPGA-specific top entity
1. Write a new top design unit that instantiates one of the provided processor templates from
[`rtl/processor_templates`](https://github.com/stnolting/neorv32/tree/master/rtl/processor_templates).
This new top unit can be a Verilog or VHDL file.
2. _Optional:_ You can also include FPGA-specific primitives like PLLs or block RAMs (but keep it simple). These components
need to be added to a FPGA-specific library in [`setups/osflow/devices`](https://github.com/stnolting/neorv32/tree/master/setups/osflow/devices).
3. Try to keep the external IO at a minimum even if the targeted FPGA boards provides cool features. Besides of clock and reset
you need to add at least one kind of IO interface like a UART, GPIO or PWM.
4. Give your new top entity file a specific name that includes the board's name and the instantiated processor template.
The name scheme is `neorv32_[board-name]_BoardTop_[template-name].[v/vhd]`.
5. Put this file in `setups/osflow/board_tops`.
6. Take a look at the iCEBreaker MinimalBoot top entity as a reference:
[`setups/osflow/board_tops/neorv32_iCEBreaker_BoardTop_MinimalBoot.vhd`](https://github.com/stnolting/neorv32/blob/master/setups/osflow/board_tops/neorv32_iCEBreaker_BoardTop_MinimalBoot.vhd)
#### 2. Pin mapping
1. Add a new constraints file to define the mapping between the your top unit's IO and the FPGA's physical pins.
You can add _all_ of the FPGA's physical pins even though just a subset is used by the new setup.
2. Name the new constraints file according to the board `[board-name].pcf`.
3. Put this file in `setups/osflow/constraints`.
4. Take a look at the iCEBreaker pin mapping as a reference:
[`setups/osflow/constraints/iCEBreaker.pcf`](https://github.com/stnolting/neorv32/blob/master/setups/osflow/constraints/iCEBreaker.pcf)
#### 3. Adding a board-specific makefile
1. Add a board-specific makefile to the `setups/osflow/boards` folder. Name the new constraints file according to the board `[board-name].mk`.
2. The makefile contains (at least) one target to build the final bitstream:
```makefile
.PHONY: all
all: bit
echo "! Built $(IMPL) for $(BOARD)"
```
3. Take a look at the iCEBreaker pin mapping as a reference:
[` setups/osflow/boards/iCEBreaker.mk`](https://github.com/stnolting/neorv32/blob/master/setups/osflow/boards/iCEBreaker.mk)
#### 4. Adding a new target to `index.mk`
1. Add a new conditional section to the boards management makefile `setups/osflow/boards/index.mk`.
2. This board-specific section sets variables that are required to run synthesis, mapping, place & route and bitstream generation:
* `CONSTRAINTS` defines the physical pin mapping file
* `PNRFLAGS` defines the FPGA-specific flags for mapping and place & route
* `IMPL` defines the setup's implementation name
```makefile
ifeq ($(BOARD),iCEBreaker)
$(info Setting constraints and implementation args for BOARD iCEBreaker)
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD).pcf
PNRFLAGS ?= --up5k --package sg48 --ignore-loops --timing-allow-fail
IMPL ?= neorv32_$(BOARD)_$(ID)
endif
```
#### 5. Adding a new target to the main makefile
1. As final step add the new setup to the main osflow makefile `setups/osflow/Makefile`.
2. Use the board's name to create a new makefile target.
* The new target should set the final bitstream's name using the `BITSTREAM` variable.
* Alternative _memory_ HDL sources like FPGA-optimized module can be set using the `NEORV32_MEM_SRC` variable.
```makefile
iCEBreaker:
$(eval BITSTREAM ?= neorv32_$(BOARD)_$(DESIGN).bit)
$(eval NEORV32_MEM_SRC ?= devices/ice40/neorv32_imem.ice40up_spram.vhd devices/ice40/neorv32_dmem.ice40up_spram.vhd)
$(MAKE) \
BITSTREAM="$(BITSTREAM)" \
NEORV32_MEM_SRC="$(NEORV32_MEM_SRC)" \
run
```
#### 6. _Optional:_ Add the new setup to the automatic "Implementation" github workflow
If you like you can add the new setup to the automatic build environment of the project. The project's "Implementation"
workflow will generate bitstreams for all configured osflow setups on every repository push. This is used to check for
regressions and also to provide up-to-date bitstreams that can be used right away.
1. Add the new setup to the job matrix file `.github/generate-job-matrix.py`.
```python
{
'board': 'iCEBreaker',
'design': 'MinimalBoot',
'bitstream': 'neorv32_iCEBreaker_MinimalBoot.bit'
},
```

View File

@ -0,0 +1,128 @@
-- #################################################################################################
-- # << NEORV32 - Example setup including the bootloader, for the AlhambraII (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_AlhambraII_BoardTop_MinimalBoot is
port (
-- external clock (12 MHz)
AlhambraII_CLK : in std_logic;
-- LED outputs
AlhambraII_LED0 : out std_logic;
AlhambraII_LED1 : out std_logic;
AlhambraII_LED2 : out std_logic;
AlhambraII_LED3 : out std_logic;
AlhambraII_LED4 : out std_logic;
AlhambraII_LED5 : out std_logic;
AlhambraII_LED6 : out std_logic;
AlhambraII_LED7 : out std_logic;
-- UART0
AlhambraII_RX : in std_logic;
AlhambraII_TX : out std_logic
);
end entity;
architecture neorv32_AlhambraII_BoardTop_MinimalBoot_rtl of neorv32_AlhambraII_BoardTop_MinimalBoot is
-- configuration --
constant f_clock_c : natural := 12000000; -- clock frequency in Hz
-- reset generator --
signal rst_cnt : std_logic_vector(8 downto 0) := (others => '0'); -- initialized by bitstream
signal sys_rstn : std_logic;
-- internal IO connection --
signal con_gpio_o : std_ulogic_vector(3 downto 0);
signal con_pwm : std_logic_vector(2 downto 0);
begin
-- Reset Generator ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
reset_generator: process(AlhambraII_CLK)
begin
if rising_edge(AlhambraII_CLK) then
if (rst_cnt(rst_cnt'left) = '0') then
rst_cnt <= std_logic_vector(unsigned(rst_cnt) + 1);
end if;
end if;
end process reset_generator;
sys_rstn <= rst_cnt(rst_cnt'left);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_MinimalBoot
generic map (
CLOCK_FREQUENCY => f_clock_c, -- clock frequency of clk_i in Hz
MEM_INT_IMEM_SIZE => 4*1024, -- size of processor-internal instruction memory in bytes
MEM_INT_DMEM_SIZE => 2*1024 -- size of processor-internal data memory in bytes
)
port map (
-- Global control --
clk_i => std_ulogic(AlhambraII_CLK),
rstn_i => std_ulogic(sys_rstn),
-- GPIO --
gpio_o => con_gpio_o,
-- primary UART --
uart_txd_o => AlhambraII_TX, -- UART0 send data
uart_rxd_i => AlhambraII_RX, -- UART0 receive data
uart_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
AlhambraII_LED0 <= con_gpio_o(0);
AlhambraII_LED1 <= con_gpio_o(1);
AlhambraII_LED2 <= con_gpio_o(2);
AlhambraII_LED3 <= con_gpio_o(3);
AlhambraII_LED4 <= '0'; -- unused
AlhambraII_LED5 <= con_pwm(0);
AlhambraII_LED6 <= con_pwm(1);
AlhambraII_LED7 <= con_pwm(2);
end architecture;

View File

@ -0,0 +1,149 @@
-- #################################################################################################
-- # << NEORV32 - Example minimal setup for the Fomu (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_Fomu_BoardTop_Minimal is
port (
-- 48MHz Clock input
clki : in std_logic;
-- LED outputs
rgb : out std_logic_vector(2 downto 0);
-- USB Pins (which should be statically driven if not being used)
usb_dp : out std_logic;
usb_dn : out std_logic;
usb_dp_pu : out std_logic
);
end entity;
architecture neorv32_Fomu_BoardTop_Minimal_rtl of neorv32_Fomu_BoardTop_Minimal is
-- configuration --
constant f_clock_c : natural := 22000000; -- PLL output clock frequency in Hz
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_pwm : std_logic_vector(2 downto 0);
begin
-- Assign USB pins to "0" so as to disconnect Fomu from
-- the host system. Otherwise it would try to talk to
-- us over USB, which wouldn't work since we have no stack.
usb_dp <= '0';
usb_dn <= '0';
usb_dp_pu <= '0';
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Settings generated by icepll -i 48 -o 21:
-- F_PLLIN: 48.000 MHz (given)
-- F_PLLOUT: 22.000 MHz (requested)
-- F_PLLOUT: 22.000 MHz (achieved)
-- FEEDBACK: SIMPLE
-- F_PFD: 16.000 MHz
-- F_VCO: 704.000 MHz
-- DIVR: 2 (4'b0010)
-- DIVF: 43 (7'b0101011)
-- DIVQ: 5 (3'b101)
-- FILTER_RANGE: 1 (3'b001)
Pll_inst : SB_PLL40_CORE
generic map (
FEEDBACK_PATH => "SIMPLE",
DIVR => x"2",
DIVF => 7x"2B",
DIVQ => 3x"5",
FILTER_RANGE => 3x"1"
)
port map (
REFERENCECLK => clki,
PLLOUTCORE => open,
PLLOUTGLOBAL => pll_clk,
EXTFEEDBACK => '0',
DYNAMICDELAY => x"00",
LOCK => pll_rstn,
BYPASS => '0',
RESETB => '1',
LATCHINPUTVALUE => '0',
SDO => open,
SDI => '0',
SCLK => '0'
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_Minimal
generic map (
CLOCK_FREQUENCY => f_clock_c -- clock frequency of clk_i in Hz
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000011",
RGB1_CURRENT => "0b000011",
RGB2_CURRENT => "0b000011"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB2PWM => con_pwm(2), -- I - blue - pwm channel 2
RGB1PWM => con_pwm(1), -- I - red - pwm channel 1 || BOOT blink
RGB0PWM => con_pwm(0), -- I - green - pwm channel 0
RGB2 => rgb(2), -- O - blue
RGB1 => rgb(1), -- O - red
RGB0 => rgb(0) -- O - green
);
end architecture;

View File

@ -0,0 +1,174 @@
-- #################################################################################################
-- # << NEORV32 - Example setup including the bootloader, for the Fomu (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_Fomu_BoardTop_MinimalBoot is
port (
-- 48MHz Clock input
clki : in std_logic;
-- LED outputs
rgb : out std_logic_vector(2 downto 0);
-- USB Pins (which should be statically driven if not being used)
usb_dp : out std_logic;
usb_dn : out std_logic;
usb_dp_pu : out std_logic
);
end entity;
architecture neorv32_Fomu_BoardTop_MinimalBoot_rtl of neorv32_Fomu_BoardTop_MinimalBoot is
-- configuration --
constant f_clock_c : natural := 18000000; -- PLL output clock frequency in Hz
-- On-chip oscillator --
signal hf_osc_clk : std_logic;
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_gpio_o : std_ulogic_vector(3 downto 0);
signal con_pwm : std_logic_vector(2 downto 0);
begin
-- Assign USB pins to "0" so as to disconnect Fomu from
-- the host system. Otherwise it would try to talk to
-- us over USB, which wouldn't work since we have no stack.
usb_dp <= '0';
usb_dn <= '0';
usb_dp_pu <= '0';
-- On-Chip HF Oscillator ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
HSOSC_inst : SB_HFOSC
generic map (
CLKHF_DIV => "0b10" -- 12 MHz
)
port map (
CLKHFPU => '1',
CLKHFEN => '1',
CLKHF => hf_osc_clk
);
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Settings generated by icepll -i 12 -o 18:
-- F_PLLIN: 12.000 MHz (given)
-- F_PLLOUT: 18.000 MHz (requested)
-- F_PLLOUT: 18.000 MHz (achieved)
-- FEEDBACK: SIMPLE
-- F_PFD: 12.000 MHz
-- F_VCO: 576.000 MHz
-- DIVR: 0 (4'b0000)
-- DIVF: 47 (7'b0101111)
-- DIVQ: 5 (3'b101)
-- FILTER_RANGE: 1 (3'b001)
Pll_inst : SB_PLL40_CORE
generic map (
FEEDBACK_PATH => "SIMPLE",
DIVR => x"0",
DIVF => 7x"2F",
DIVQ => 3x"5",
FILTER_RANGE => 3x"1"
)
port map (
REFERENCECLK => hf_osc_clk,
PLLOUTCORE => open,
PLLOUTGLOBAL => pll_clk,
EXTFEEDBACK => '0',
DYNAMICDELAY => x"00",
LOCK => pll_rstn,
BYPASS => '0',
RESETB => '1',
LATCHINPUTVALUE => '0',
SDO => open,
SDI => '0',
SCLK => '0'
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_MinimalBoot
generic map (
CLOCK_FREQUENCY => f_clock_c -- clock frequency of clk_i in Hz
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- GPIO --
gpio_o => con_gpio_o,
-- primary UART --
uart_txd_o => open, -- UART0 send data
uart_rxd_i => '0', -- UART0 receive data
uart_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000011",
RGB1_CURRENT => "0b000011",
RGB2_CURRENT => "0b000011"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB2PWM => con_pwm(2), -- I - blue - pwm channel 2
RGB1PWM => con_pwm(1) or con_gpio_o(0), -- I - red - pwm channel 1 || BOOT blink
RGB0PWM => con_pwm(0), -- I - green - pwm channel 0
RGB2 => rgb(2), -- O - blue
RGB1 => rgb(1), -- O - red
RGB0 => rgb(0) -- O - green
);
end architecture;

View File

@ -0,0 +1,139 @@
-- #################################################################################################
-- # << NEORV32 - Example setup including the bootloader, for the Fomu (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_Fomu_BoardTop_MixedLanguage is
port (
-- 48MHz Clock input
clki : in std_logic;
-- LED outputs
rgb : out std_logic_vector(2 downto 0);
-- USB Pins (which should be statically driven if not being used)
usb_dp : out std_logic;
usb_dn : out std_logic;
usb_dp_pu : out std_logic
);
end entity;
architecture neorv32_Fomu_BoardTop_MixedLanguage_rtl of neorv32_Fomu_BoardTop_MixedLanguage is
-- configuration --
constant f_clock_c : natural := 18000000; -- PLL output clock frequency in Hz
component neorv32_Fomu_MixedLanguage_ClkGen
port (
clk_o : out std_logic;
rstn_o : out std_logic
);
end component;
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_gpio_o : std_ulogic_vector(3 downto 0);
signal con_pwm : std_logic_vector(2 downto 0);
begin
-- Assign USB pins to "0" so as to disconnect Fomu from
-- the host system. Otherwise it would try to talk to
-- us over USB, which wouldn't work since we have no stack.
usb_dp <= '0';
usb_dn <= '0';
usb_dp_pu <= '0';
-- On-Chip HF Oscillator and System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
Clk_inst : neorv32_Fomu_MixedLanguage_ClkGen
port map (
clk_o => pll_clk,
rstn_o => pll_rstn
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_MinimalBoot
generic map (
CLOCK_FREQUENCY => f_clock_c -- clock frequency of clk_i in Hz
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- GPIO --
gpio_o => con_gpio_o,
-- primary UART --
uart_txd_o => open, -- UART0 send data
uart_rxd_i => '0', -- UART0 receive data
uart_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000011",
RGB1_CURRENT => "0b000011",
RGB2_CURRENT => "0b000011"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB2PWM => con_pwm(2), -- I - blue - pwm channel 2
RGB1PWM => con_pwm(1) or con_gpio_o(0), -- I - red - pwm channel 1 || BOOT blink
RGB0PWM => con_pwm(0), -- I - green - pwm channel 0
RGB2 => rgb(2), -- O - blue
RGB1 => rgb(1), -- O - red
RGB0 => rgb(0) -- O - green
);
end architecture;

View File

@ -0,0 +1,185 @@
-- #################################################################################################
-- # << NEORV32 - Example setup for the Fomu (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_Fomu_BoardTop_UP5KDemo is
port (
-- 48MHz Clock input
clki : in std_logic;
-- LED outputs
rgb : out std_logic_vector(2 downto 0);
-- USB Pins (which should be statically driven if not being used)
usb_dp : out std_logic;
usb_dn : out std_logic;
usb_dp_pu : out std_logic
);
end entity;
architecture neorv32_Fomu_BoardTop_UP5KDemo_rtl of neorv32_Fomu_BoardTop_UP5KDemo is
-- configuration --
constant f_clock_c : natural := 18000000; -- PLL output clock frequency in Hz
-- On-chip oscillator --
signal hf_osc_clk : std_logic;
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_pwm : std_ulogic_vector(2 downto 0);
signal con_gpio_o : std_ulogic_vector(3 downto 0);
begin
-- Assign USB pins to "0" so as to disconnect Fomu from
-- the host system. Otherwise it would try to talk to
-- us over USB, which wouldn't work since we have no stack.
usb_dp <= '0';
usb_dn <= '0';
usb_dp_pu <= '0';
-- On-Chip HF Oscillator ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
HSOSC_inst : SB_HFOSC
generic map (
CLKHF_DIV => "0b10" -- 12 MHz
)
port map (
CLKHFPU => '1',
CLKHFEN => '1',
CLKHF => hf_osc_clk
);
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Settings generated by icepll -i 12 -o 18:
-- F_PLLIN: 12.000 MHz (given)
-- F_PLLOUT: 18.000 MHz (requested)
-- F_PLLOUT: 18.000 MHz (achieved)
-- FEEDBACK: SIMPLE
-- F_PFD: 12.000 MHz
-- F_VCO: 576.000 MHz
-- DIVR: 0 (4'b0000)
-- DIVF: 47 (7'b0101111)
-- DIVQ: 5 (3'b101)
-- FILTER_RANGE: 1 (3'b001)
Pll_inst : SB_PLL40_CORE
generic map (
FEEDBACK_PATH => "SIMPLE",
DIVR => x"0",
DIVF => 7x"2F",
DIVQ => 3x"5",
FILTER_RANGE => 3x"1"
)
port map (
REFERENCECLK => hf_osc_clk,
PLLOUTCORE => open,
PLLOUTGLOBAL => pll_clk,
EXTFEEDBACK => '0',
DYNAMICDELAY => x"00",
LOCK => pll_rstn,
BYPASS => '0',
RESETB => '1',
LATCHINPUTVALUE => '0',
SDO => open,
SDI => '0',
SCLK => '0'
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_UP5KDemo
generic map (
CLOCK_FREQUENCY => f_clock_c -- clock frequency of clk_i in Hz
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- primary UART --
uart_txd_o => open,
uart_rxd_i => '0',
uart_rts_o => open,
uart_cts_i => '0',
-- SPI to on-board flash --
flash_sck_o => open,
flash_sdo_o => open,
flash_sdi_i => '0',
flash_csn_o => open,
-- SPI to IO pins --
spi_sck_o => open,
spi_sdo_o => open,
spi_sdi_i => '0',
spi_csn_o => open,
-- TWI --
twi_sda_io => open,
twi_scl_io => open,
-- GPIO --
gpio_i => (others=>'0'),
gpio_o => con_gpio_o,
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000011",
RGB1_CURRENT => "0b000011",
RGB2_CURRENT => "0b000011"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB2PWM => con_pwm(2), -- I - blue - pwm channel 2
RGB1PWM => con_pwm(1) or con_gpio_o(0), -- I - red - pwm channel 1 || BOOT blink
RGB0PWM => con_pwm(0), -- I - green - pwm channel 0
RGB2 => rgb(2), -- O - blue
RGB1 => rgb(1), -- O - red
RGB0 => rgb(0) -- O - green
);
end architecture;

View File

@ -0,0 +1,130 @@
-- #################################################################################################
-- # << NEORV32 - Example setup including the bootloader, for the OrangeCrab (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 ECP5;
use ECP5.components.all; -- for device primitives and macros
entity neorv32_OrangeCrab_BoardTop_MinimalBoot is
port (
-- Clock and Reset inputs
OrangeCrab_CLK : in std_logic;
OrangeCrab_RST_N : in std_logic;
-- LED outputs
OrangeCrab_LED_RGB_R : out std_logic;
OrangeCrab_LED_RGB_G : out std_logic;
OrangeCrab_LED_RGB_B : out std_logic;
-- UART0
OrangeCrab_GPIO_0 : in std_logic;
OrangeCrab_GPIO_1 : out std_logic;
OrangeCrab_GPIO_9 : out std_logic;
-- USB Pins (which should be statically driven if not being used)
OrangeCrab_USB_D_P : out std_logic;
OrangeCrab_USB_D_N : out std_logic;
OrangeCrab_USB_DP_PU : out std_logic
);
end entity;
architecture neorv32_OrangeCrab_BoardTop_MinimalBoot_rtl of neorv32_OrangeCrab_BoardTop_MinimalBoot is
-- configuration --
constant f_clock_c : natural := 24000000; -- PLL output clock frequency in Hz
-- Globals
signal pll_clk: std_logic;
-- internal IO connection --
signal con_pwm : std_logic_vector(2 downto 0);
signal con_gpio_o : std_ulogic_vector(3 downto 0);
begin
-- Assign USB pins to "0" so as to disconnect OrangeCrab from
-- the host system. Otherwise it would try to talk to
-- us over USB, which wouldn't work since we have no stack.
OrangeCrab_USB_D_P <= '0';
OrangeCrab_USB_D_N <= '0';
OrangeCrab_USB_DP_PU <= '0';
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
PLL_inst: EHXPLLL
generic map (
CLKI_DIV => 2, -- from `ecppll -i 48 -o 24`
CLKFB_DIV => 1,
CLKOP_DIV => 25
)
port map (
CLKI => OrangeCrab_CLK,
CLKFB => pll_clk,
ENCLKOP => '1',
CLKOP => pll_clk,
LOCK => OrangeCrab_GPIO_9
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_MinimalBoot
generic map (
CLOCK_FREQUENCY => f_clock_c, -- clock frequency of clk_i in Hz
MEM_INT_IMEM_SIZE => 16*1024,
MEM_INT_DMEM_SIZE => 8*1024
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(OrangeCrab_RST_N),
-- GPIO --
gpio_o => con_gpio_o,
-- primary UART --
uart_txd_o => OrangeCrab_GPIO_1, -- UART0 send data
uart_rxd_i => OrangeCrab_GPIO_0, -- UART0 receive data
uart_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
OrangeCrab_LED_RGB_R <= con_pwm(0) or not con_gpio_o(0);
OrangeCrab_LED_RGB_G <= con_pwm(1);
OrangeCrab_LED_RGB_B <= con_pwm(2);
end architecture;

View File

@ -0,0 +1,110 @@
-- #################################################################################################
-- # << NEORV32 - Example setup including the bootloader, for the ULX3S (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 ECP5;
use ECP5.components.all; -- for device primitives and macros
entity neorv32_ULX3S_BoardTop_MinimalBoot is
port (
-- Clock and Reset inputs
ULX3S_CLK : in std_logic;
ULX3S_RST_N : in std_logic;
-- LED outputs
ULX3S_LED0 : out std_logic;
ULX3S_LED1 : out std_logic;
ULX3S_LED2 : out std_logic;
ULX3S_LED3 : out std_logic;
ULX3S_LED4 : out std_logic;
ULX3S_LED5 : out std_logic;
ULX3S_LED6 : out std_logic;
ULX3S_LED7 : out std_logic;
-- UART0
ULX3S_RX : in std_logic;
ULX3S_TX : out std_logic
);
end entity;
architecture neorv32_ULX3S_BoardTop_MinimalBoot_rtl of neorv32_ULX3S_BoardTop_MinimalBoot is
-- configuration --
constant f_clock_c : natural := 25000000; -- clock frequency in Hz
-- internal IO connection --
signal con_pwm : std_logic_vector(2 downto 0);
signal con_gpio_o : std_ulogic_vector(3 downto 0);
begin
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_MinimalBoot
generic map (
CLOCK_FREQUENCY => f_clock_c, -- clock frequency of clk_i in Hz
MEM_INT_IMEM_SIZE => 16*1024,
MEM_INT_DMEM_SIZE => 8*1024
)
port map (
-- Global control --
clk_i => std_ulogic(ULX3S_CLK),
rstn_i => std_ulogic(ULX3S_RST_N),
-- GPIO --
gpio_o => con_gpio_o,
-- primary UART --
uart_txd_o => ULX3S_TX, -- UART0 send data
uart_rxd_i => ULX3S_RX, -- UART0 receive data
uart_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ULX3S_LED0 <= con_gpio_o(0);
ULX3S_LED1 <= con_gpio_o(1);
ULX3S_LED2 <= con_gpio_o(2);
ULX3S_LED3 <= con_gpio_o(3);
ULX3S_LED4 <= '0'; -- unused
ULX3S_LED5 <= con_pwm(0);
ULX3S_LED6 <= con_pwm(1);
ULX3S_LED7 <= con_pwm(2);
end architecture;

View File

@ -0,0 +1,163 @@
-- #################################################################################################
-- # << NEORV32 - Example setup for the tinyVision.ai Inc. "UPduino v3" (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_UPduino_BoardTop_MinimalBoot is
port (
-- UART (uart0) --
uart_txd_o : out std_ulogic;
uart_rxd_i : in std_ulogic;
-- GPIO --
gpio_o : out std_ulogic_vector(3 downto 0);
-- PWM (to on-board RGB power LED) --
pwm_o : out std_logic_vector(2 downto 0)
);
end entity;
architecture neorv32_UPduino_BoardTop_MinimalBoot_rtl of neorv32_UPduino_BoardTop_MinimalBoot is
-- configuration --
constant f_clock_c : natural := 18000000; -- PLL output clock frequency in Hz
-- On-chip oscillator --
signal hf_osc_clk : std_logic;
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_pwm : std_logic_vector(2 downto 0);
begin
-- On-Chip HF Oscillator ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
HSOSC_inst : SB_HFOSC
generic map (
CLKHF_DIV => "0b10" -- 12 MHz
)
port map (
CLKHFPU => '1',
CLKHFEN => '1',
CLKHF => hf_osc_clk
);
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Settings generated by icepll -i 12 -o 18:
-- F_PLLIN: 12.000 MHz (given)
-- F_PLLOUT: 18.000 MHz (requested)
-- F_PLLOUT: 18.000 MHz (achieved)
-- FEEDBACK: SIMPLE
-- F_PFD: 12.000 MHz
-- F_VCO: 576.000 MHz
-- DIVR: 0 (4'b0000)
-- DIVF: 47 (7'b0101111)
-- DIVQ: 5 (3'b101)
-- FILTER_RANGE: 1 (3'b001)
Pll_inst : SB_PLL40_CORE
generic map (
FEEDBACK_PATH => "SIMPLE",
DIVR => x"0",
DIVF => 7x"2F",
DIVQ => 3x"5",
FILTER_RANGE => 3x"1"
)
port map (
REFERENCECLK => hf_osc_clk,
PLLOUTCORE => open,
PLLOUTGLOBAL => pll_clk,
EXTFEEDBACK => '0',
DYNAMICDELAY => x"00",
LOCK => pll_rstn,
BYPASS => '0',
RESETB => '1',
LATCHINPUTVALUE => '0',
SDO => open,
SDI => '0',
SCLK => '0'
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_MinimalBoot
generic map (
CLOCK_FREQUENCY => f_clock_c -- clock frequency of clk_i in Hz
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- GPIO --
gpio_o => gpio_o,
-- primary UART --
uart_txd_o => uart_txd_o, -- UART0 send data
uart_rxd_i => uart_rxd_i, -- UART0 receive data
uart_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000011",
RGB1_CURRENT => "0b000011",
RGB2_CURRENT => "0b000011"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB0PWM => con_pwm(1), -- I - green - pwm channel 1
RGB1PWM => con_pwm(2), -- I - blue - pwm channel 2
RGB2PWM => con_pwm(0), -- I - red - pwm channel 0
RGB2 => pwm_o(2), -- O - red
RGB1 => pwm_o(1), -- O - blue
RGB0 => pwm_o(0) -- O - green
);
end architecture;

View File

@ -0,0 +1,204 @@
-- #################################################################################################
-- # << NEORV32 - Example setup for the tinyVision.ai Inc. "UPduino v3" (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_UPduino_BoardTop_UP5KDemo is
port (
-- UART (uart0) --
uart_txd_o : out std_ulogic;
uart_rxd_i : in std_ulogic;
-- SPI to on-board flash --
flash_sck_o : out std_ulogic;
flash_sdo_o : out std_ulogic;
flash_sdi_i : in std_ulogic;
flash_csn_o : out std_ulogic; -- NEORV32.SPI_CS(0)
-- SPI to IO pins --
spi_sck_o : out std_ulogic;
spi_sdo_o : out std_ulogic;
spi_sdi_i : in std_ulogic;
spi_csn_o : out std_ulogic; -- NEORV32.SPI_CS(1)
-- TWI --
twi_sda_io : inout std_logic;
twi_scl_io : inout std_logic;
-- GPIO --
gpio_i : in std_ulogic_vector(3 downto 0);
gpio_o : out std_ulogic_vector(3 downto 0);
-- PWM (to on-board RGB power LED) --
pwm_o : out std_ulogic_vector(2 downto 0)
);
end entity;
architecture neorv32_UPduino_BoardTop_UP5KDemo_rtl of neorv32_UPduino_BoardTop_UP5KDemo is
-- configuration --
constant f_clock_c : natural := 18000000; -- PLL output clock frequency in Hz
-- On-chip oscillator --
signal hf_osc_clk : std_logic;
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_pwm : std_ulogic_vector(2 downto 0);
signal con_spi_sdi : std_ulogic;
signal con_spi_csn : std_ulogic;
begin
-- On-Chip HF Oscillator ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
HSOSC_inst : SB_HFOSC
generic map (
CLKHF_DIV => "0b10" -- 12 MHz
)
port map (
CLKHFPU => '1',
CLKHFEN => '1',
CLKHF => hf_osc_clk
);
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Settings generated by icepll -i 12 -o 18:
-- F_PLLIN: 12.000 MHz (given)
-- F_PLLOUT: 18.000 MHz (requested)
-- F_PLLOUT: 18.000 MHz (achieved)
-- FEEDBACK: SIMPLE
-- F_PFD: 12.000 MHz
-- F_VCO: 576.000 MHz
-- DIVR: 0 (4'b0000)
-- DIVF: 47 (7'b0101111)
-- DIVQ: 5 (3'b101)
-- FILTER_RANGE: 1 (3'b001)
Pll_inst : SB_PLL40_CORE
generic map (
FEEDBACK_PATH => "SIMPLE",
DIVR => x"0",
DIVF => 7x"2F",
DIVQ => 3x"5",
FILTER_RANGE => 3x"1"
)
port map (
REFERENCECLK => hf_osc_clk,
PLLOUTCORE => open,
PLLOUTGLOBAL => pll_clk,
EXTFEEDBACK => '0',
DYNAMICDELAY => x"00",
LOCK => pll_rstn,
BYPASS => '0',
RESETB => '1',
LATCHINPUTVALUE => '0',
SDO => open,
SDI => '0',
SCLK => '0'
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_UP5KDemo
generic map (
CLOCK_FREQUENCY => f_clock_c -- clock frequency of clk_i in Hz
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- primary UART --
uart_txd_o => uart_txd_o,
uart_rxd_i => uart_rxd_i,
uart_rts_o => open,
uart_cts_i => '0',
-- SPI to on-board flash --
flash_sck_o => flash_sck_o,
flash_sdo_o => flash_sdo_o,
flash_sdi_i => flash_sdi_i,
flash_csn_o => flash_csn_o,
-- SPI to IO pins --
spi_sck_o => spi_sck_o,
spi_sdo_o => spi_sdo_o,
spi_sdi_i => con_spi_sdi,
spi_csn_o => con_spi_csn,
-- TWI --
twi_sda_io => twi_sda_io,
twi_scl_io => twi_scl_io,
-- GPIO --
gpio_i => gpio_i,
gpio_o => gpio_o,
-- PWM (to on-board RGB power LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- SPI sdi read-back --
spi_csn_o <= con_spi_csn;
con_spi_sdi <= flash_sdi_i when (con_spi_csn = '0') else spi_sdi_i;
-- RGB --
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000001",
RGB1_CURRENT => "0b000001",
RGB2_CURRENT => "0b000001"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB0PWM => con_pwm(1), -- I - green - pwm channel 1
RGB1PWM => con_pwm(2), -- I - bluee - pwm channel 2
RGB2PWM => con_pwm(0), -- I - red - pwm channel 0
RGB2 => pwm_o(2), -- O - red
RGB1 => pwm_o(1), -- O - blue
RGB0 => pwm_o(0) -- O - green
);
end architecture;

View File

@ -0,0 +1,163 @@
-- #################################################################################################
-- # << NEORV32 - Example setup for the tinyVision.ai Inc. "UPduino v3" (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_iCEBreaker_BoardTop_MinimalBoot is
port (
-- UART (uart0) --
uart_txd_o : out std_ulogic;
uart_rxd_i : in std_ulogic;
-- GPIO --
gpio_o : out std_ulogic_vector(3 downto 0);
-- PWM (to on-board RGB power LED) --
pwm_o : out std_logic_vector(2 downto 0)
);
end entity;
architecture neorv32_iCEBreaker_BoardTop_MinimalBoot_rtl of neorv32_iCEBreaker_BoardTop_MinimalBoot is
-- configuration --
constant f_clock_c : natural := 18000000; -- PLL output clock frequency in Hz
-- On-chip oscillator --
signal hf_osc_clk : std_logic;
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_pwm : std_logic_vector(2 downto 0);
begin
-- On-Chip HF Oscillator ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
HSOSC_inst : SB_HFOSC
generic map (
CLKHF_DIV => "0b10" -- 12 MHz
)
port map (
CLKHFPU => '1',
CLKHFEN => '1',
CLKHF => hf_osc_clk
);
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Settings generated by icepll -i 12 -o 18:
-- F_PLLIN: 12.000 MHz (given)
-- F_PLLOUT: 18.000 MHz (requested)
-- F_PLLOUT: 18.000 MHz (achieved)
-- FEEDBACK: SIMPLE
-- F_PFD: 12.000 MHz
-- F_VCO: 576.000 MHz
-- DIVR: 0 (4'b0000)
-- DIVF: 47 (7'b0101111)
-- DIVQ: 5 (3'b101)
-- FILTER_RANGE: 1 (3'b001)
Pll_inst : SB_PLL40_CORE
generic map (
FEEDBACK_PATH => "SIMPLE",
DIVR => x"0",
DIVF => 7x"2F",
DIVQ => 3x"5",
FILTER_RANGE => 3x"1"
)
port map (
REFERENCECLK => hf_osc_clk,
PLLOUTCORE => open,
PLLOUTGLOBAL => pll_clk,
EXTFEEDBACK => '0',
DYNAMICDELAY => x"00",
LOCK => pll_rstn,
BYPASS => '0',
RESETB => '1',
LATCHINPUTVALUE => '0',
SDO => open,
SDI => '0',
SCLK => '0'
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_MinimalBoot
generic map (
CLOCK_FREQUENCY => f_clock_c -- clock frequency of clk_i in Hz
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- GPIO --
gpio_o => gpio_o,
-- primary UART --
uart_txd_o => uart_txd_o, -- UART0 send data
uart_rxd_i => uart_rxd_i, -- UART0 receive data
uart_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000011",
RGB1_CURRENT => "0b000011",
RGB2_CURRENT => "0b000011"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB0PWM => con_pwm(1), -- I - green - pwm channel 1
RGB1PWM => con_pwm(2), -- I - blue - pwm channel 2
RGB2PWM => con_pwm(0), -- I - red - pwm channel 0
RGB2 => pwm_o(2), -- O - red
RGB1 => pwm_o(1), -- O - blue
RGB0 => pwm_o(0) -- O - green
);
end architecture;

View File

@ -0,0 +1,205 @@
-- #################################################################################################
-- # << NEORV32 - Example setup for the tinyVision.ai Inc. "UPduino v3" (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_iCEBreaker_BoardTop_UP5KDemo is
port (
user_reset_btn : in std_ulogic;
-- UART (uart0) --
uart_txd_o : out std_ulogic;
uart_rxd_i : in std_ulogic;
-- SPI to on-board flash --
flash_sck_o : out std_ulogic;
flash_sdo_o : out std_ulogic;
flash_sdi_i : in std_ulogic;
flash_csn_o : out std_ulogic; -- NEORV32.SPI_CS(0)
-- SPI to IO pins --
spi_sck_o : out std_ulogic;
spi_sdo_o : out std_ulogic;
spi_sdi_i : in std_ulogic;
spi_csn_o : out std_ulogic; -- NEORV32.SPI_CS(1)
-- TWI --
twi_sda_io : inout std_logic;
twi_scl_io : inout std_logic;
-- GPIO --
gpio_i : in std_ulogic_vector(3 downto 0);
gpio_o : out std_ulogic_vector(3 downto 0);
-- PWM (to on-board RGB power LED) --
pwm_o : out std_ulogic_vector(2 downto 0)
);
end entity;
architecture neorv32_iCEBreaker_BoardTop_UP5KDemo_rtl of neorv32_iCEBreaker_BoardTop_UP5KDemo is
-- configuration --
constant f_clock_c : natural := 18000000; -- PLL output clock frequency in Hz
-- On-chip oscillator --
signal hf_osc_clk : std_logic;
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_pwm : std_ulogic_vector(2 downto 0);
signal con_spi_sdi : std_ulogic;
signal con_spi_csn : std_ulogic;
begin
-- On-Chip HF Oscillator ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
HSOSC_inst : SB_HFOSC
generic map (
CLKHF_DIV => "0b10" -- 12 MHz
)
port map (
CLKHFPU => '1',
CLKHFEN => '1',
CLKHF => hf_osc_clk
);
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Settings generated by icepll -i 12 -o 18:
-- F_PLLIN: 12.000 MHz (given)
-- F_PLLOUT: 18.000 MHz (requested)
-- F_PLLOUT: 18.000 MHz (achieved)
-- FEEDBACK: SIMPLE
-- F_PFD: 12.000 MHz
-- F_VCO: 576.000 MHz
-- DIVR: 0 (4'b0000)
-- DIVF: 47 (7'b0101111)
-- DIVQ: 5 (3'b101)
-- FILTER_RANGE: 1 (3'b001)
Pll_inst : SB_PLL40_CORE
generic map (
FEEDBACK_PATH => "SIMPLE",
DIVR => x"0",
DIVF => 7x"2F",
DIVQ => 3x"5",
FILTER_RANGE => 3x"1"
)
port map (
REFERENCECLK => hf_osc_clk,
PLLOUTCORE => open,
PLLOUTGLOBAL => pll_clk,
EXTFEEDBACK => '0',
DYNAMICDELAY => x"00",
LOCK => pll_rstn,
BYPASS => '0',
RESETB => user_reset_btn,
LATCHINPUTVALUE => '0',
SDO => open,
SDI => '0',
SCLK => '0'
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_UP5KDemo
generic map (
CLOCK_FREQUENCY => f_clock_c -- clock frequency of clk_i in Hz
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- primary UART --
uart_txd_o => uart_txd_o,
uart_rxd_i => uart_rxd_i,
uart_rts_o => open,
uart_cts_i => '0',
-- SPI to on-board flash --
flash_sck_o => flash_sck_o,
flash_sdo_o => flash_sdo_o,
flash_sdi_i => flash_sdi_i,
flash_csn_o => flash_csn_o,
-- SPI to IO pins --
spi_sck_o => spi_sck_o,
spi_sdo_o => spi_sdo_o,
spi_sdi_i => con_spi_sdi,
spi_csn_o => con_spi_csn,
-- TWI --
twi_sda_io => twi_sda_io,
twi_scl_io => twi_scl_io,
-- GPIO --
gpio_i => gpio_i,
gpio_o => gpio_o,
-- PWM (to on-board RGB power LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- SPI sdi read-back --
spi_csn_o <= con_spi_csn;
con_spi_sdi <= flash_sdi_i when (con_spi_csn = '0') else spi_sdi_i;
-- RGB --
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000001",
RGB1_CURRENT => "0b000001",
RGB2_CURRENT => "0b000001"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB0PWM => con_pwm(1), -- I - green - pwm channel 1
RGB1PWM => con_pwm(2), -- I - bluee - pwm channel 2
RGB2PWM => con_pwm(0), -- I - red - pwm channel 0
RGB2 => pwm_o(2), -- O - red
RGB1 => pwm_o(1), -- O - blue
RGB0 => pwm_o(0) -- O - green
);
end architecture;

View File

@ -0,0 +1,172 @@
-- #################################################################################################
-- # << NEORV32 - Example setup with an external clock, for the iCESugar (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_iCESugar_BoardTop_Minimal is
port (
-- 48MHz Clock input
iCESugarv15_CLK : in std_logic;
-- UART0
iCESugarv15_RX : in std_logic;
iCESugarv15_TX : out std_logic;
-- LED outputs
iCESugarv15_LED_R : out std_logic;
iCESugarv15_LED_G : out std_logic;
iCESugarv15_LED_B : out std_logic;
-- USB Pins (which should be statically driven if not being used)
iCESugarv15_USB_DP : out std_logic;
iCESugarv15_USB_DN : out std_logic;
iCESugarv15_USB_DP_PU : out std_logic
);
end entity;
architecture neorv32_iCESugar_BoardTop_Minimal_rtl of neorv32_iCESugar_BoardTop_Minimal is
-- configuration --
constant f_clock_c : natural := 22000000; -- PLL output clock frequency in Hz
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_gpio_o : std_ulogic_vector(3 downto 0);
signal con_pwm : std_logic_vector(2 downto 0);
begin
-- Assign USB pins to "0" so as to disconnect iCESugar from
-- the host system. Otherwise it would try to talk to
-- us over USB, which wouldn't work since we have no stack.
iCESugarv15_USB_DP <= '0';
iCESugarv15_USB_DN <= '0';
iCESugarv15_USB_DP_PU <= '0';
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Settings generated by icepll -i 12 -o 22:
-- F_PLLIN: 12.000 MHz (given)
-- F_PLLOUT: 22.000 MHz (requested)
-- F_PLLOUT: 22.000 MHz (achieved)
-- FEEDBACK: SIMPLE
-- F_PFD: 12.000 MHz
-- F_VCO: 708.000 MHz
-- DIVR: 0 (4'b0000)
-- DIVF: 58 (7'b0111010)
-- DIVQ: 5 (3'b101)
-- FILTER_RANGE: 1 (3'b001)
Pll_inst : SB_PLL40_PAD
generic map (
FEEDBACK_PATH => "SIMPLE",
DIVR => x"0",
DIVF => 7x"3A",
DIVQ => 3x"5",
FILTER_RANGE => 3x"1"
)
port map (
PACKAGEPIN => iCESugarv15_CLK,
PLLOUTCORE => open,
PLLOUTGLOBAL => pll_clk,
EXTFEEDBACK => '0',
DYNAMICDELAY => x"00",
LOCK => pll_rstn,
BYPASS => '0',
RESETB => '1',
LATCHINPUTVALUE => '0',
SDO => open,
SDI => '0',
SCLK => '0'
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_MinimalBoot
generic map (
CLOCK_FREQUENCY => f_clock_c, -- clock frequency of clk_i in Hz
CPU_EXTENSION_RISCV_A => false,
CPU_EXTENSION_RISCV_C => false,
CPU_EXTENSION_RISCV_E => false,
CPU_EXTENSION_RISCV_M => false,
CPU_EXTENSION_RISCV_U => false,
CPU_EXTENSION_RISCV_Zfinx => false,
CPU_EXTENSION_RISCV_Zicsr => true,
CPU_EXTENSION_RISCV_Zifencei => false
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- GPIO --
gpio_o => con_gpio_o,
-- primary UART --
uart_txd_o => iCESugarv15_TX, -- UART0 send data
uart_rxd_i => iCESugarv15_RX, -- UART0 receive data
uart_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000011",
RGB1_CURRENT => "0b000011",
RGB2_CURRENT => "0b000011"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB2PWM => con_pwm(2), -- I - blue - pwm channel 2
RGB1PWM => con_pwm(1) or con_gpio_o(0), -- I - red - pwm channel 1 || BOOT blink
RGB0PWM => con_pwm(0), -- I - green - pwm channel 0
RGB2 => iCESugarv15_LED_B, -- O - blue
RGB1 => iCESugarv15_LED_R, -- O - red
RGB0 => iCESugarv15_LED_G -- O - green
);
end architecture;

View File

@ -0,0 +1,177 @@
-- #################################################################################################
-- # << NEORV32 - Example setup including the bootloader, for the iCESugar (c) Board >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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 iCE40;
use iCE40.components.all; -- for device primitives and macros
entity neorv32_iCESugar_BoardTop_MinimalBoot is
port (
-- LED outputs
iCESugarv15_LED_R : out std_logic;
iCESugarv15_LED_G : out std_logic;
iCESugarv15_LED_B : out std_logic;
-- UART0
iCESugarv15_RX : in std_logic;
iCESugarv15_TX : out std_logic;
-- USB Pins (which should be statically driven if not being used)
iCESugarv15_USB_DP : out std_logic;
iCESugarv15_USB_DN : out std_logic;
iCESugarv15_USB_DP_PU : out std_logic
);
end entity;
architecture neorv32_iCESugar_BoardTop_MinimalBoot_rtl of neorv32_iCESugar_BoardTop_MinimalBoot is
-- configuration --
constant f_clock_c : natural := 18000000; -- PLL output clock frequency in Hz
-- On-chip oscillator --
signal hf_osc_clk : std_logic;
-- Globals
signal pll_rstn : std_logic;
signal pll_clk : std_logic;
-- internal IO connection --
signal con_gpio_o : std_ulogic_vector(3 downto 0);
signal con_pwm : std_logic_vector(2 downto 0);
begin
-- Assign USB pins to "0" so as to disconnect iCESugar from
-- the host system. Otherwise it would try to talk to
-- us over USB, which wouldn't work since we have no stack.
iCESugarv15_USB_DP <= '0';
iCESugarv15_USB_DN <= '0';
iCESugarv15_USB_DP_PU <= '0';
-- On-Chip HF Oscillator ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
HSOSC_inst : SB_HFOSC
generic map (
CLKHF_DIV => "0b10" -- 12 MHz
)
port map (
CLKHFPU => '1',
CLKHFEN => '1',
CLKHF => hf_osc_clk
);
-- System PLL -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Settings generated by icepll -i 12 -o 18:
-- F_PLLIN: 12.000 MHz (given)
-- F_PLLOUT: 18.000 MHz (requested)
-- F_PLLOUT: 18.000 MHz (achieved)
-- FEEDBACK: SIMPLE
-- F_PFD: 12.000 MHz
-- F_VCO: 576.000 MHz
-- DIVR: 0 (4'b0000)
-- DIVF: 47 (7'b0101111)
-- DIVQ: 5 (3'b101)
-- FILTER_RANGE: 1 (3'b001)
Pll_inst : SB_PLL40_CORE
generic map (
FEEDBACK_PATH => "SIMPLE",
DIVR => x"0",
DIVF => 7x"2F",
DIVQ => 3x"5",
FILTER_RANGE => 3x"1"
)
port map (
REFERENCECLK => hf_osc_clk,
PLLOUTCORE => open,
PLLOUTGLOBAL => pll_clk,
EXTFEEDBACK => '0',
DYNAMICDELAY => x"00",
LOCK => pll_rstn,
BYPASS => '0',
RESETB => '1',
LATCHINPUTVALUE => '0',
SDO => open,
SDI => '0',
SCLK => '0'
);
-- The core of the problem ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_inst: entity work.neorv32_ProcessorTop_MinimalBoot
generic map (
CLOCK_FREQUENCY => f_clock_c -- clock frequency of clk_i in Hz
)
port map (
-- Global control --
clk_i => std_ulogic(pll_clk),
rstn_i => std_ulogic(pll_rstn),
-- GPIO --
gpio_o => con_gpio_o,
-- primary UART --
uart_txd_o => iCESugarv15_TX, -- UART0 send data
uart_rxd_i => iCESugarv15_RX, -- UART0 receive data
uart_rts_o => open, -- hw flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart_cts_i => '0', -- hw flow control: UART0.TX allowed to transmit, low-active, optional
-- PWM (to on-board RGB LED) --
pwm_o => con_pwm
);
-- IO Connection --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
RGB_inst: SB_RGBA_DRV
generic map (
CURRENT_MODE => "0b1",
RGB0_CURRENT => "0b000011",
RGB1_CURRENT => "0b000011",
RGB2_CURRENT => "0b000011"
)
port map (
CURREN => '1', -- I
RGBLEDEN => '1', -- I
RGB2PWM => con_pwm(2), -- I - blue - pwm channel 2
RGB1PWM => con_pwm(1) or con_gpio_o(0), -- I - red - pwm channel 1 || BOOT blink
RGB0PWM => con_pwm(0), -- I - green - pwm channel 0
RGB2 => iCESugarv15_LED_B, -- O - blue
RGB1 => iCESugarv15_LED_R, -- O - red
RGB0 => iCESugarv15_LED_G -- O - green
);
end architecture;

View File

@ -0,0 +1,4 @@
.PHONY: all
all: bit
echo "! Built $(IMPL) for $(BOARD)"

View File

@ -0,0 +1,16 @@
.PHONY: all
# Default target: run all required targets to build the DFU image.
all: $(IMPL).dfu
echo "! Built $(IMPL) for $(BOARD) $(FOMU_REV)"
# Use dfu-suffix to generate the DFU image from the FPGA bitstream.
${IMPL}.dfu: $(IMPL).bit
$(COPY) $< $@
dfu-suffix -v 1209 -p 70b1 -a $@
# Use df-util to load the DFU image onto the Fomu.
load: $(IMPL).dfu
dfu-util -D $<
.PHONY: load

View File

@ -0,0 +1,4 @@
.PHONY: all
all: bit
echo "! Built $(IMPL) for $(BOARD)"

View File

@ -0,0 +1,4 @@
.PHONY: all
all: bit
echo "! Built $(IMPL) for $(BOARD)"

View File

@ -0,0 +1,4 @@
.PHONY: all
all: bit
echo "! Built $(IMPL) for $(BOARD)"

View File

@ -0,0 +1,4 @@
.PHONY: all
all: bit
echo "! Built $(IMPL) for $(BOARD)"

View File

@ -0,0 +1,4 @@
.PHONY: all
all: bit
echo "! Built $(IMPL) for $(BOARD)"

View File

@ -0,0 +1,107 @@
PCF_PATH ?= constraints
ifeq ($(BOARD),Fomu)
$(info Setting constraints and implementation args for BOARD Fomu)
# Different Fomu hardware revisions are wired differently and thus
# require different configurations for yosys and nextpnr.
# Configuration is performed by setting the environment variable FOMU_REV accordingly.
FOMU_REV ?= pvt
ifeq ($(FOMU_REV),evt1)
YOSYSFLAGS ?= -D EVT=1 -D EVT1=1 -D HAVE_PMOD=1
PNRFLAGS ?= --up5k --package sg48
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD)-evt2.pcf
else ifeq ($(FOMU_REV),evt2)
YOSYSFLAGS ?= -D EVT=1 -D EVT2=1 -D HAVE_PMOD=1
PNRFLAGS ?= --up5k --package sg48
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD)-$(FOMU_REV).pcf
else ifeq ($(FOMU_REV),evt3)
YOSYSFLAGS ?= -D EVT=1 -D EVT3=1 -D HAVE_PMOD=1
PNRFLAGS ?= --up5k --package sg48
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD)-$(FOMU_REV).pcf
else ifeq ($(FOMU_REV),hacker)
YOSYSFLAGS ?= -D HACKER=1
PNRFLAGS ?= --up5k --package uwg30
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD)-$(FOMU_REV).pcf
else ifeq ($(FOMU_REV),pvt)
YOSYSFLAGS ?= -D PVT=1
PNRFLAGS ?= --up5k --package uwg30
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD)-$(FOMU_REV).pcf
else
$(error Unrecognized FOMU_REV value. must be "evt1", "evt2", "evt3", "pvt", or "hacker")
endif
IMPL := neorv32_Fomu_$(FOMU_REV)_$(ID)
endif
ifeq ($(BOARD),iCESugar)
$(info Setting constraints and implementation args for BOARD iCESugar)
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD).pcf
PNRFLAGS ?= --up5k --package sg48 --ignore-loops --timing-allow-fail
IMPL ?= neorv32_$(BOARD)_$(ID)
endif
ifeq ($(BOARD),UPduino)
$(info Setting constraints and implementation args for BOARD UPduino)
UPduino_REV ?= v3
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD)_v3.pcf
PNRFLAGS ?= --up5k --package sg48 --ignore-loops --timing-allow-fail
IMPL ?= neorv32_$(BOARD)_$(UPduino_REV)_$(ID)
endif
ifeq ($(BOARD),iCEBreaker)
$(info Setting constraints and implementation args for BOARD iCEBreaker)
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD).pcf
PNRFLAGS ?= --up5k --package sg48 --ignore-loops --timing-allow-fail
IMPL ?= neorv32_$(BOARD)_$(ID)
endif
ifeq ($(BOARD),OrangeCrab)
$(info Setting constraints and implementation args for BOARD OrangeCrab)
DEVICE_SERIES = ecp5
OrangeCrab_REV ?= r02-25F
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD).lpf
PNRFLAGS ?= --25k --package CSFBGA285 --ignore-loops --timing-allow-fail
IMPL ?= neorv32_$(BOARD)_$(OrangeCrab_REV)_$(ID)
endif
ifeq ($(BOARD),AlhambraII)
$(info Setting constraints and implementation args for BOARD AlhambraII)
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD).pcf
PNRFLAGS ?= --hx8k --package tq144:4k --ignore-loops --timing-allow-fail
IMPL ?= neorv32_$(BOARD)_$(ID)
endif
ifeq ($(BOARD),ULX3S)
$(info Setting constraints and implementation args for BOARD ULX3S)
DEVICE_SERIES = ecp5
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD).lpf
PNRFLAGS ?= --85k --freq 25 --package CABGA381 --ignore-loops --timing-allow-fail
IMPL ?= neorv32_$(BOARD)_$(ID)
endif

View File

@ -0,0 +1,39 @@
ID ?= impl_1
include boards/index.mk
ifndef TOP
$(error TOP needs to be specified!)
endif
include filesets.mk
ifndef DESIGN_SRC
ifndef BOARD_SRC
$(error Neither DESIGN_SRC nor BOARD_SRC were set!)
endif
endif
include tools.mk
ifdef GHDL_PLUGIN_MODULE
YOSYSFLAGS += -m $(GHDL_PLUGIN_MODULE)
endif
include synthesis.mk
include PnR_Bit.mk
.PHONY: syn impl bit svf clean
syn: ${IMPL}.json
impl: ${IMPL}.${PNR2BIT_EXT}
bit: ${IMPL}.bit
ifeq ($(DEVICE_SERIES),ecp5)
svf: ${IMPL}.svf
endif
clean:
rm -rf *.{${PNR2BIT_EXT},bit,cf,dfu,history,json,o,svf} *-report.txt
include boards/$(BOARD).mk

View File

@ -0,0 +1,24 @@
# -----------------------------------------------------------------------------
#- Alhambra II constraint file (.pcf)
#- By Carlos Dominguez
#- May - 2021
#- GPL license
#- Repo: https://github.com/zipotron/neorv32
# -----------------------------------------------------------------------------
# UART port (on-board FTDI)
set_io AlhambraII_TX 61 # output (ser-tx)
set_io AlhambraII_RX 62 # input (ser-rx)
#> External clock (12 MHz)
set_io AlhambraII_CLK 49
#> On-Board LEDs
set_io AlhambraII_LED0 45
set_io AlhambraII_LED1 44
set_io AlhambraII_LED2 43
set_io AlhambraII_LED3 42
set_io AlhambraII_LED4 41
set_io AlhambraII_LED5 39
set_io AlhambraII_LED6 38
set_io AlhambraII_LED7 37

View File

@ -0,0 +1,34 @@
# Configuration for the Fomu 'evt2' board
set_io clki 44
set_io clki_alt 20
set_io rgb[0] 39
set_io rgb[1] 40
set_io rgb[2] 41
set_io pmod[0] 25
set_io pmod[1] 26
set_io pmod[2] 27
set_io pmod[3] 28
set_io user[0] 48
set_io user[1] 47
set_io user[2] 46
set_io user[3] 45
set_io user[4] 42
set_io user[5] 38
set_io spi_mosi 14
set_io spi_miso 17
set_io spi_clk 15
set_io spi_cs 16
set_io spi_io2 18
set_io spi_io3 19
set_io uart_tx 21
set_io uart_rx 13
set_io usb_dn 37
set_io usb_dp 34
set_io usb_dp_pu 35
set_io usb_dn_pu 36
set_io dbg[0] 20
set_io dbg[1] 12
set_io dbg[2] 11
set_io dbg[3] 23
set_io dbg[4] 10
set_io dbg[5] 9

View File

@ -0,0 +1,34 @@
# Configuration for the Fomu 'evt3' board
set_io rgb[0] 39
set_io rgb[1] 40
set_io rgb[2] 41
set_io pmod[0] 28
set_io pmod[1] 27
set_io pmod[2] 26
set_io pmod[3] 23
set_io clki_alt 20
set_io clki 44
set_io user[0] 48
set_io user[1] 47
set_io user[2] 46
set_io user[3] 45
set_io user[4] 42
set_io user[5] 38
set_io spi_mosi 14
set_io spi_miso 17
set_io spi_clk 15
set_io spi_io2 18
set_io spi_io3 19
set_io spi_cs 16
set_io uart_tx 21
set_io uart_rx 13
set_io usb_dn 37
set_io usb_dp 34
set_io usb_dp_pu 35
set_io usb_dn_pu 36
set_io dbg[0] 20
set_io dbg[1] 12
set_io dbg[2] 11
set_io dbg[3] 25
set_io dbg[4] 10
set_io dbg[5] 9

View File

@ -0,0 +1,16 @@
# Configuration for the Fomu 'hacker' board
set_io clki F5 # Clock input from 48MHz Oscillator
set_io rgb[0] A5 # Blue LED
set_io rgb[1] B5 # Green LED
set_io rgb[2] C5 # Red LED
set_io user[0] F4 # User touch pad 1
set_io user[1] E5 # User touch pad 2
set_io user[2] E4 # User touch pad 3
set_io user[3] F2 # User touch pad 4
set_io spi_mosi F1 # SPI Master Out, Slave In Pin
set_io spi_miso E1 # SPI Master In, Slave Out Pin
set_io spi_clk D1 # SPI Master Clock Output Pin
set_io spi_cs C1 # SPI Chip Select
set_io usb_dn A2 # USB D- pad
set_io usb_dp A4 # USB D+ pad
set_io usb_dp_pu D5 # USB D+ pull up (indicates device connected)

View File

@ -0,0 +1,18 @@
# Configuration for the Fomu 'pvt' board
set_io clki F4 # Clock input from 48MHz Oscillator
set_io rgb[0] A5 # Blue LED
set_io rgb[1] B5 # Green LED
set_io rgb[2] C5 # Red LED
set_io user[0] E4 # User touch pad 1
set_io user[1] D5 # User touch pad 2
set_io user[2] E5 # User touch pad 3
set_io user[3] F5 # User touch pad 4
set_io spi_mosi F1 # SPI Master Out, Slave In Pin
set_io spi_miso E1 # SPI Master In, Slave Out Pin
set_io spi_clk D1 # SPI Master Clock Output Pin
set_io spi_cs C1 # SPI Chip Select
set_io spi_io2 F2
set_io spi_io3 B1
set_io usb_dn A2 # USB D- pad
set_io usb_dp A1 # USB D+ pad
set_io usb_dp_pu A4 # USB D+ pull up (indicates device connected)

View File

@ -0,0 +1,278 @@
#| OrangeCrab-r02-25F
LOCATE COMP "OrangeCrab_CLK" SITE "A9";
IOBUF PORT "OrangeCrab_CLK" IO_TYPE=LVCMOS33;
FREQUENCY PORT "OrangeCrab_CLK" 48.0 MHz;
LOCATE COMP "OrangeCrab_RST_N" SITE "V17";
IOBUF PORT "OrangeCrab_RST_N" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_LED_RGB_R" SITE "K4";
IOBUF PORT "OrangeCrab_LED_RGB_R" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_LED_RGB_G" SITE "M3";
IOBUF PORT "OrangeCrab_LED_RGB_G" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_LED_RGB_B" SITE "J3";
IOBUF PORT "OrangeCrab_LED_RGB_B" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_USR_BTN" SITE "J17";
IOBUF PORT "OrangeCrab_USR_BTN" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_USB_D_P" SITE "N1";
IOBUF PORT "OrangeCrab_USB_D_P" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_USB_D_N" SITE "M2";
IOBUF PORT "OrangeCrab_USB_D_N" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_USB_DP_PU" SITE "N2";
IOBUF PORT "OrangeCrab_USB_DP_PU" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_GPIO_0" SITE "N17";
IOBUF PORT "OrangeCrab_GPIO_0" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_0" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_1" SITE "M18";
IOBUF PORT "OrangeCrab_GPIO_1" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_1" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_5" SITE "B10";
IOBUF PORT "OrangeCrab_GPIO_5" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_5" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_6" SITE "B9";
IOBUF PORT "OrangeCrab_GPIO_6" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_6" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_9" SITE "C8";
IOBUF PORT "OrangeCrab_GPIO_9" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_9" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_10" SITE "B8";
IOBUF PORT "OrangeCrab_GPIO_10" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_10" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_11" SITE "A8";
IOBUF PORT "OrangeCrab_GPIO_11" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_11" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_12" SITE "H2";
IOBUF PORT "OrangeCrab_GPIO_12" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_12" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_13" SITE "J2";
IOBUF PORT "OrangeCrab_GPIO_13" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_13" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_A0" SITE "L4";
IOBUF PORT "OrangeCrab_GPIO_A0" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_A0" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_A1" SITE "N3";
IOBUF PORT "OrangeCrab_GPIO_A1" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_A1" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_A2" SITE "N4";
IOBUF PORT "OrangeCrab_GPIO_A2" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_A2" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_GPIO_A3" SITE "H4";
IOBUF PORT "OrangeCrab_GPIO_A3" IO_TYPE=LVCMOS33;
IOBUF PORT "OrangeCrab_GPIO_A3" PULLMODE=DOWN;
LOCATE COMP "OrangeCrab_DDRAM_A[0]" SITE "C4";
IOBUF PORT "OrangeCrab_DDRAM_A[0]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[0]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[1]" SITE "D2";
IOBUF PORT "OrangeCrab_DDRAM_A[1]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[1]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[2]" SITE "D3";
IOBUF PORT "OrangeCrab_DDRAM_A[2]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[2]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[3]" SITE "A3";
IOBUF PORT "OrangeCrab_DDRAM_A[3]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[3]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[4]" SITE "A4";
IOBUF PORT "OrangeCrab_DDRAM_A[4]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[4]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[5]" SITE "D4";
IOBUF PORT "OrangeCrab_DDRAM_A[5]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[5]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[6]" SITE "C3";
IOBUF PORT "OrangeCrab_DDRAM_A[6]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[6]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[7]" SITE "B2";
IOBUF PORT "OrangeCrab_DDRAM_A[7]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[7]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[8]" SITE "B1";
IOBUF PORT "OrangeCrab_DDRAM_A[8]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[8]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[9]" SITE "D1";
IOBUF PORT "OrangeCrab_DDRAM_A[9]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[9]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[10]" SITE "A7";
IOBUF PORT "OrangeCrab_DDRAM_A[10]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[10]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[11]" SITE "C2";
IOBUF PORT "OrangeCrab_DDRAM_A[11]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[11]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[12]" SITE "B6";
IOBUF PORT "OrangeCrab_DDRAM_A[12]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[12]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[13]" SITE "C1";
IOBUF PORT "OrangeCrab_DDRAM_A[13]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[13]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[14]" SITE "A2";
IOBUF PORT "OrangeCrab_DDRAM_A[14]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[14]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_A[15]" SITE "C7";
IOBUF PORT "OrangeCrab_DDRAM_A[15]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_A[15]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_BA[0]" SITE "D6";
IOBUF PORT "OrangeCrab_DDRAM_BA[0]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_BA[0]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_BA[1]" SITE "B7";
IOBUF PORT "OrangeCrab_DDRAM_BA[1]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_BA[1]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_BA[2]" SITE "A6";
IOBUF PORT "OrangeCrab_DDRAM_BA[2]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_BA[2]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_RAS_N" SITE "C12";
IOBUF PORT "OrangeCrab_DDRAM_RAS_N" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_RAS_N" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_CAS_N" SITE "D13";
IOBUF PORT "OrangeCrab_DDRAM_CAS_N" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_CAS_N" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_WE_N" SITE "B12";
IOBUF PORT "OrangeCrab_DDRAM_WE_N" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_WE_N" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_CS_N" SITE "A12";
IOBUF PORT "OrangeCrab_DDRAM_CS_N" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_CS_N" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_DM[0]" SITE "D16";
IOBUF PORT "OrangeCrab_DDRAM_DM[0]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DM[0]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_DM[1]" SITE "G16";
IOBUF PORT "OrangeCrab_DDRAM_DM[1]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DM[1]" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_DQ[0]" SITE "C17";
IOBUF PORT "OrangeCrab_DDRAM_DQ[0]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[0]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[0]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[1]" SITE "D15";
IOBUF PORT "OrangeCrab_DDRAM_DQ[1]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[1]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[1]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[2]" SITE "B17";
IOBUF PORT "OrangeCrab_DDRAM_DQ[2]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[2]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[2]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[3]" SITE "C16";
IOBUF PORT "OrangeCrab_DDRAM_DQ[3]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[3]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[3]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[4]" SITE "A15";
IOBUF PORT "OrangeCrab_DDRAM_DQ[4]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[4]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[4]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[5]" SITE "B13";
IOBUF PORT "OrangeCrab_DDRAM_DQ[5]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[5]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[5]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[6]" SITE "A17";
IOBUF PORT "OrangeCrab_DDRAM_DQ[6]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[6]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[6]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[7]" SITE "A13";
IOBUF PORT "OrangeCrab_DDRAM_DQ[7]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[7]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[7]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[8]" SITE "F17";
IOBUF PORT "OrangeCrab_DDRAM_DQ[8]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[8]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[8]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[9]" SITE "F16";
IOBUF PORT "OrangeCrab_DDRAM_DQ[9]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[9]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[9]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[10]" SITE "G15";
IOBUF PORT "OrangeCrab_DDRAM_DQ[10]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[10]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[10]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[11]" SITE "F15";
IOBUF PORT "OrangeCrab_DDRAM_DQ[11]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[11]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[11]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[12]" SITE "J16";
IOBUF PORT "OrangeCrab_DDRAM_DQ[12]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[12]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[12]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[13]" SITE "C18";
IOBUF PORT "OrangeCrab_DDRAM_DQ[13]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[13]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[13]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[14]" SITE "H16";
IOBUF PORT "OrangeCrab_DDRAM_DQ[14]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[14]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[14]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQ[15]" SITE "F18";
IOBUF PORT "OrangeCrab_DDRAM_DQ[15]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQ[15]" IO_TYPE=SSTL135_I;
IOBUF PORT "OrangeCrab_DDRAM_DQ[15]" TERMINATION=OFF;
LOCATE COMP "OrangeCrab_DDRAM_DQS_P[0]" SITE "B15";
IOBUF PORT "OrangeCrab_DDRAM_DQS_P[0]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQS_P[0]" IO_TYPE=SSTL135D_I;
IOBUF PORT "OrangeCrab_DDRAM_DQS_P[0]" TERMINATION=OFF;
IOBUF PORT "OrangeCrab_DDRAM_DQS_P[0]" DIFFRESISTOR=100;
LOCATE COMP "OrangeCrab_DDRAM_DQS_P[1]" SITE "G18";
IOBUF PORT "OrangeCrab_DDRAM_DQS_P[1]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_DQS_P[1]" IO_TYPE=SSTL135D_I;
IOBUF PORT "OrangeCrab_DDRAM_DQS_P[1]" TERMINATION=OFF;
IOBUF PORT "OrangeCrab_DDRAM_DQS_P[1]" DIFFRESISTOR=100;
LOCATE COMP "OrangeCrab_DDRAM_CLK_P" SITE "J18";
IOBUF PORT "OrangeCrab_DDRAM_CLK_P" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_CLK_P" IO_TYPE=SSTL135D_I;
LOCATE COMP "OrangeCrab_DDRAM_CKE" SITE "D18";
IOBUF PORT "OrangeCrab_DDRAM_CKE" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_CKE" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_ODT" SITE "C13";
IOBUF PORT "OrangeCrab_DDRAM_ODT" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_ODT" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_RESET_N" SITE "L18";
IOBUF PORT "OrangeCrab_DDRAM_RESET_N" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_RESET_N" IO_TYPE=SSTL135_I;
LOCATE COMP "OrangeCrab_DDRAM_VCCIO[0]" SITE "K16";
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[0]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[0]" IO_TYPE=SSTL135_II;
LOCATE COMP "OrangeCrab_DDRAM_VCCIO[1]" SITE "D17";
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[1]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[1]" IO_TYPE=SSTL135_II;
LOCATE COMP "OrangeCrab_DDRAM_VCCIO[2]" SITE "K15";
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[2]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[2]" IO_TYPE=SSTL135_II;
LOCATE COMP "OrangeCrab_DDRAM_VCCIO[3]" SITE "K17";
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[3]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[3]" IO_TYPE=SSTL135_II;
LOCATE COMP "OrangeCrab_DDRAM_VCCIO[4]" SITE "B18";
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[4]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[4]" IO_TYPE=SSTL135_II;
LOCATE COMP "OrangeCrab_DDRAM_VCCIO[5]" SITE "C6";
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[5]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_VCCIO[5]" IO_TYPE=SSTL135_II;
LOCATE COMP "OrangeCrab_DDRAM_GND[0]" SITE "L15";
IOBUF PORT "OrangeCrab_DDRAM_GND[0]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_GND[0]" IO_TYPE=SSTL135_II;
LOCATE COMP "OrangeCrab_DDRAM_GND[1]" SITE "L16";
IOBUF PORT "OrangeCrab_DDRAM_GND[1]" SLEWRATE=FAST;
IOBUF PORT "OrangeCrab_DDRAM_GND[1]" IO_TYPE=SSTL135_II;
LOCATE COMP "OrangeCrab_SPIFLASH_CS_N" SITE "U17";
IOBUF PORT "OrangeCrab_SPIFLASH_CS_N" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_SPIFLASH_DQ[0]" SITE "U18";
IOBUF PORT "OrangeCrab_SPIFLASH_DQ[0]" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_SPIFLASH_DQ[1]" SITE "T18";
IOBUF PORT "OrangeCrab_SPIFLASH_DQ[1]" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_SPIFLASH_DQ[2]" SITE "R18";
IOBUF PORT "OrangeCrab_SPIFLASH_DQ[2]" IO_TYPE=LVCMOS33;
LOCATE COMP "OrangeCrab_SPIFLASH_DQ[3]" SITE "N18";
IOBUF PORT "OrangeCrab_SPIFLASH_DQ[3]" IO_TYPE=LVCMOS33;

View File

@ -0,0 +1,598 @@
BLOCK RESETPATHS;
BLOCK ASYNCPATHS;
## ULX3S v2.x.x and v3.0.x
# The clock "usb" and "gpdi" sheet
LOCATE COMP "ULX3S_CLK" SITE "G2";
IOBUF PORT "ULX3S_CLK" PULLMODE=NONE IO_TYPE=LVCMOS33;
FREQUENCY PORT "ULX3S_CLK" 25 MHZ;
# JTAG and SPI FLASH voltage 3.3V and options to boot from SPI flash
# write to FLASH possible any time from JTAG:
SYSCONFIG CONFIG_IOVOLTAGE=3.3 COMPRESS_CONFIG=ON MCCLK_FREQ=62 SLAVE_SPI_PORT=DISABLE MASTER_SPI_PORT=ENABLE SLAVE_PARALLEL_PORT=DISABLE;
# write to FLASH possible from user bitstream:
# SYSCONFIG CONFIG_IOVOLTAGE=3.3 COMPRESS_CONFIG=ON MCCLK_FREQ=62 SLAVE_SPI_PORT=DISABLE MASTER_SPI_PORT=DISABLE SLAVE_PARALLEL_PORT=DISABLE;
## USBSERIAL FTDI-FPGA serial port "usb" sheet
LOCATE COMP "ULX3S_TX" SITE "L4"; # FPGA transmits to ftdi
LOCATE COMP "ULX3S_RX" SITE "M1"; # FPGA receives from ftdi
LOCATE COMP "ftdi_nrts" SITE "M3"; # FPGA receives
LOCATE COMP "ftdi_ndtr" SITE "N1"; # FPGA receives
LOCATE COMP "ftdi_txden" SITE "L3"; # FPGA receives
IOBUF PORT "ULX3S_TX" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "ULX3S_RX" PULLMODE=UP IO_TYPE=LVCMOS33;
IOBUF PORT "ftdi_nrts" PULLMODE=UP IO_TYPE=LVCMOS33;
IOBUF PORT "ftdi_ndtr" PULLMODE=UP IO_TYPE=LVCMOS33;
IOBUF PORT "ftdi_txden" PULLMODE=UP IO_TYPE=LVCMOS33;
## LED indicators "blinkey" and "gpio" sheet
LOCATE COMP "ULX3S_LED7" SITE "H3";
LOCATE COMP "ULX3S_LED6" SITE "E1";
LOCATE COMP "ULX3S_LED5" SITE "E2";
LOCATE COMP "ULX3S_LED4" SITE "D1";
LOCATE COMP "ULX3S_LED3" SITE "D2";
LOCATE COMP "ULX3S_LED2" SITE "C1";
LOCATE COMP "ULX3S_LED1" SITE "C2";
LOCATE COMP "ULX3S_LED0" SITE "B2";
IOBUF PORT "ULX3S_LED0" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "ULX3S_LED1" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "ULX3S_LED2" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "ULX3S_LED3" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "ULX3S_LED4" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "ULX3S_LED5" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "ULX3S_LED6" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "ULX3S_LED7" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
## Pushbuttons "blinkey", "flash", "power", "gpdi" sheet
LOCATE COMP "ULX3S_RST_N" SITE "D6"; # BTN_PWRn (inverted logic)
LOCATE COMP "btn[1]" SITE "R1"; # FIRE1
LOCATE COMP "btn[2]" SITE "T1"; # FIRE2
LOCATE COMP "btn[3]" SITE "R18"; # UP W1->R18
LOCATE COMP "btn[4]" SITE "V1"; # DOWN
LOCATE COMP "btn[5]" SITE "U1"; # LEFT
LOCATE COMP "btn[6]" SITE "H16"; # RIGHT Y2->H16
IOBUF PORT "ULX3S_RST_N" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "btn[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "btn[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "btn[3]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "btn[4]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "btn[5]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "btn[6]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
## DIP switch "blinkey", "gpio" sheet
LOCATE COMP "sw[0]" SITE "E8"; # SW1
LOCATE COMP "sw[1]" SITE "D8"; # SW2
LOCATE COMP "sw[2]" SITE "D7"; # SW3
LOCATE COMP "sw[3]" SITE "E7"; # SW4
IOBUF PORT "sw[0]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sw[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sw[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sw[3]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
## SPI OLED DISPLAY SSD1331 (Color) or SSD1306 (B/W) "blinkey", "usb" sheet
LOCATE COMP "oled_clk" SITE "P4";
LOCATE COMP "oled_mosi" SITE "P3";
LOCATE COMP "oled_dc" SITE "P1";
LOCATE COMP "oled_resn" SITE "P2";
LOCATE COMP "oled_csn" SITE "N2";
IOBUF PORT "oled_clk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "oled_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "oled_dc" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "oled_resn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "oled_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
## SPI Flash chip "flash" sheet
LOCATE COMP "flash_csn" SITE "R2";
LOCATE COMP "flash_clk" SITE "U3";
LOCATE COMP "flash_mosi" SITE "W2";
LOCATE COMP "flash_miso" SITE "V2";
LOCATE COMP "flash_holdn" SITE "W1";
LOCATE COMP "flash_wpn" SITE "Y2";
#LOCATE COMP "flash_csspin" SITE "AJ3";
#LOCATE COMP "flash_initn" SITE "AG4";
#LOCATE COMP "flash_done" SITE "AJ4";
#LOCATE COMP "flash_programn" SITE "AH4";
#LOCATE COMP "flash_cfg_select[0]" SITE "AM4";
#LOCATE COMP "flash_cfg_select[1]" SITE "AL4";
#LOCATE COMP "flash_cfg_select[2]" SITE "AK4";
IOBUF PORT "flash_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "flash_clk" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "flash_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "flash_miso" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "flash_holdn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "flash_wpn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "flash_csspin" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "flash_initn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "flash_done" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "flash_programn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "flash_cfg_select[0]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "flash_cfg_select[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "flash_cfg_select[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
## SD card "sdcard", "usb" sheet
# wifi_gpio2,4,12,13,14,15 are shared with SD card.
# If any of wifi_gpio2,4,12,13 is used in toplevel, don't use sd_d[].
# If SD is used in 1-bit SPI mode, wifi_gpio4,12 = sd_d[1,2] are free,
LOCATE COMP "sd_clk" SITE "H2"; # sd_clk WiFi_GPIO14
LOCATE COMP "sd_cmd" SITE "J1"; # sd_cmd_di (MOSI) WiFi GPIO15
LOCATE COMP "sd_d[0]" SITE "J3"; # sd_d0_do (MISO) WiFi GPIO2
LOCATE COMP "sd_d[1]" SITE "H1"; # sd_d1_irq WiFi GPIO4
LOCATE COMP "sd_d[2]" SITE "K1"; # sd_d2 WiFi_GPIO12
LOCATE COMP "sd_d[3]" SITE "K2"; # sd_d3_csn WiFi_GPIO13
LOCATE COMP "sd_wp" SITE "P5"; # not connected
LOCATE COMP "sd_cdn" SITE "N5"; # not connected
IOBUF PORT "sd_clk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sd_cmd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sd_d[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sd_d[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sd_d[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; # WiFi GPIO12 pulldown bootstrapping without 3.3V efuse
IOBUF PORT "sd_d[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sd_wp" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sd_cdn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
## ADC SPI (MAX11123) "analog", "ram" sheet
# input lines shared with GP,GN14-17
LOCATE COMP "adc_csn" SITE "R17";
LOCATE COMP "adc_mosi" SITE "R16";
LOCATE COMP "adc_miso" SITE "U16";
LOCATE COMP "adc_sclk" SITE "P17";
IOBUF PORT "adc_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "adc_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "adc_miso" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "adc_sclk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
## Audio 4-bit DAC "analog", "gpio" sheet
# output impedance: 75 ohm
# Stereo 16 ohm earphones, analog audio,
# SPDIF digital audio and composite video.
LOCATE COMP "audio_l[3]" SITE "B3"; # JACK TIP (left audio)
LOCATE COMP "audio_l[2]" SITE "C3";
LOCATE COMP "audio_l[1]" SITE "D3";
LOCATE COMP "audio_l[0]" SITE "E4";
LOCATE COMP "audio_r[3]" SITE "C5"; # JACK RING1 (right audio)
LOCATE COMP "audio_r[2]" SITE "D5";
LOCATE COMP "audio_r[1]" SITE "B5";
LOCATE COMP "audio_r[0]" SITE "A3";
LOCATE COMP "audio_v[3]" SITE "E5"; # JACK RING2 (video or digital audio)
LOCATE COMP "audio_v[2]" SITE "F5";
LOCATE COMP "audio_v[1]" SITE "F2";
LOCATE COMP "audio_v[0]" SITE "H5";
IOBUF PORT "audio_l[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_l[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_l[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_l[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_r[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_r[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_r[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_r[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_v[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_v[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_v[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "audio_v[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
## WiFi ESP-32 "wifi", "usb", "flash" sheet
# wifi_gpio2,4,12,13,14,15 are shared with SD card.
# If any of wifi_gpio2,4,12,13 is used in toplevel, don't use sd_d[].
# If SD is used in 1-bit SPI mode, wifi_gpio4,12 = sd_d[1,2] are free,
# other pins are shared with GP/GN, and JTAG
LOCATE COMP "wifi_en" SITE "F1"; # enable/reset WiFi
LOCATE COMP "wifi_rxd" SITE "K3"; # FPGA transmits to WiFi
LOCATE COMP "wifi_txd" SITE "K4"; # FPGA receives from WiFi
LOCATE COMP "wifi_gpio0" SITE "L2";
LOCATE COMP "wifi_gpio5" SITE "N4"; # WIFI LED
LOCATE COMP "wifi_gpio16" SITE "L1"; # Serial1 RX
LOCATE COMP "wifi_gpio17" SITE "N3"; # Serial1 TX
# LOCATE COMP "prog_done" SITE "Y3"; # not GPIO, always active
# wifi lines shared with SD card
LOCATE COMP "wifi_gpio2" SITE "J3"; # sd_d0_do (MISO) WiFi GPIO2
LOCATE COMP "wifi_gpio4" SITE "H1"; # sd_d1_irq WiFi GPIO4
LOCATE COMP "wifi_gpio12" SITE "K1"; # sd_d2 WiFi_GPIO12
LOCATE COMP "wifi_gpio13" SITE "K2"; # sd_d3_csn WiFi_GPIO13
LOCATE COMP "wifi_gpio14" SITE "H2"; # sd_clk WiFi_GPIO14
LOCATE COMP "wifi_gpio15" SITE "J1"; # sd_cmd_di (MOSI) WiFi GPIO15
# wifi lines shared with JTAG
# LOCATE COMP "wifi_gpio21" SITE "U5"; # JTAG TMS
# LOCATE COMP "wifi_gpio18" SITE "T5"; # JTAG TCK
# LOCATE COMP "wifi_gpio23" SITE "R5"; # JTAG TDI
# LOCATE COMP "wifi_gpio19" SITE "V4"; # JTAG TDO
IOBUF PORT "wifi_en" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "wifi_rxd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "wifi_txd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "wifi_gpio0" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "wifi_gpio5" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4; # pull down or drive 0 for esp32 programming
IOBUF PORT "wifi_gpio16" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "wifi_gpio17" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
# IOBUF PORT "prog_done" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
## PCB antenna 433 MHz (may be also used for FM) "usb" sheet
LOCATE COMP "ant_433mhz" SITE "G1";
IOBUF PORT "ant_433mhz" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
## Second USB port "US2" going directly into FPGA "usb", "ram" sheet
LOCATE COMP "ULX3S_USB_D_P" SITE "E16"; # single ended or differential input only
LOCATE COMP "ULX3S_USB_D_N" SITE "F16";
IOBUF PORT "ULX3S_USB_D_P" PULLMODE=NONE IO_TYPE=LVCMOS33D DRIVE=16;
IOBUF PORT "ULX3S_USB_D_N" PULLMODE=NONE IO_TYPE=LVCMOS33D DRIVE=16;
LOCATE COMP "usb_fpga_bd_dp" SITE "D15"; # single-ended bidirectional
LOCATE COMP "usb_fpga_bd_dn" SITE "E15";
IOBUF PORT "usb_fpga_bd_dp" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "usb_fpga_bd_dn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
LOCATE COMP "ULX3S_USB_DP_PU" SITE "B12"; # pull up/down control
LOCATE COMP "ULX3S_USB_DN_PU" SITE "C12";
IOBUF PORT "ULX3S_USB_DP_PU" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
IOBUF PORT "ULX3S_USB_DN_PU" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
## JTAG ESP-32 "usb" sheet
# connected to FT231X and ESP-32
# commented out because those are dedicated pins, not directly useable as GPIO
# but could be used by some vendor-specific JTAG bridging (boundary scan) module
#LOCATE COMP "jtag_tdi" SITE "R5"; # FTDI_nRI FPGA receives
#LOCATE COMP "jtag_tdo" SITE "V4"; # FTDI_nCTS FPGA transmits
#LOCATE COMP "jtag_tck" SITE "T5"; # FTDI_nDSR FPGA receives
#LOCATE COMP "jtag_tms" SITE "U5"; # FTDI_nDCD FPGA receives
#IOBUF PORT "jtag_tdi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "jtag_tdo" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "jtag_tck" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
#IOBUF PORT "jtag_tms" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
## SDRAM "ram" sheet
LOCATE COMP "sdram_clk" SITE "F19";
LOCATE COMP "sdram_cke" SITE "F20";
LOCATE COMP "sdram_csn" SITE "P20";
LOCATE COMP "sdram_wen" SITE "T20";
LOCATE COMP "sdram_rasn" SITE "R20";
LOCATE COMP "sdram_casn" SITE "T19";
LOCATE COMP "sdram_a[0]" SITE "M20";
LOCATE COMP "sdram_a[1]" SITE "M19";
LOCATE COMP "sdram_a[2]" SITE "L20";
LOCATE COMP "sdram_a[3]" SITE "L19";
LOCATE COMP "sdram_a[4]" SITE "K20";
LOCATE COMP "sdram_a[5]" SITE "K19";
LOCATE COMP "sdram_a[6]" SITE "K18";
LOCATE COMP "sdram_a[7]" SITE "J20";
LOCATE COMP "sdram_a[8]" SITE "J19";
LOCATE COMP "sdram_a[9]" SITE "H20";
LOCATE COMP "sdram_a[10]" SITE "N19";
LOCATE COMP "sdram_a[11]" SITE "G20";
LOCATE COMP "sdram_a[12]" SITE "G19";
LOCATE COMP "sdram_ba[0]" SITE "P19";
LOCATE COMP "sdram_ba[1]" SITE "N20";
LOCATE COMP "sdram_dqm[0]" SITE "U19";
LOCATE COMP "sdram_dqm[1]" SITE "E20";
LOCATE COMP "sdram_d[0]" SITE "J16";
LOCATE COMP "sdram_d[1]" SITE "L18";
LOCATE COMP "sdram_d[2]" SITE "M18";
LOCATE COMP "sdram_d[3]" SITE "N18";
LOCATE COMP "sdram_d[4]" SITE "P18";
LOCATE COMP "sdram_d[5]" SITE "T18";
LOCATE COMP "sdram_d[6]" SITE "T17";
LOCATE COMP "sdram_d[7]" SITE "U20";
LOCATE COMP "sdram_d[8]" SITE "E19";
LOCATE COMP "sdram_d[9]" SITE "D20";
LOCATE COMP "sdram_d[10]" SITE "D19";
LOCATE COMP "sdram_d[11]" SITE "C20";
LOCATE COMP "sdram_d[12]" SITE "E18";
LOCATE COMP "sdram_d[13]" SITE "F18";
LOCATE COMP "sdram_d[14]" SITE "J18";
LOCATE COMP "sdram_d[15]" SITE "J17";
IOBUF PORT "sdram_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_cke" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_csn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_wen" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_rasn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_casn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_a[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_ba[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_ba[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_dqm[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_dqm[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[13]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[14]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "sdram_d[15]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
# GPDI differential interface (Video) "gpdi" sheet
LOCATE COMP "gpdi_dp[0]" SITE "A16"; # Blue +
LOCATE COMP "gpdi_dn[0]" SITE "B16"; # Blue -
LOCATE COMP "gpdi_dp[1]" SITE "A14"; # Green +
LOCATE COMP "gpdi_dn[1]" SITE "C14"; # Green -
LOCATE COMP "gpdi_dp[2]" SITE "A12"; # Red +
LOCATE COMP "gpdi_dn[2]" SITE "A13"; # Red -
LOCATE COMP "gpdi_dp[3]" SITE "A17"; # Clock +
LOCATE COMP "gpdi_dn[3]" SITE "B18"; # Clock -
LOCATE COMP "gpdi_util" SITE "A19"; # add 10k parallel to C
LOCATE COMP "gpdi_hpd" SITE "B20"; # add 549ohm parallel to C
LOCATE COMP "gpdi_cec" SITE "A18";
LOCATE COMP "gpdi_sda" SITE "B19"; # I2C shared with RTC
LOCATE COMP "gpdi_scl" SITE "E12"; # I2C shared with RTC C12->E12
IOBUF PORT "gpdi_dp[0]" IO_TYPE=LVCMOS33D DRIVE=4;
IOBUF PORT "gpdi_dn[0]" IO_TYPE=LVCMOS33D DRIVE=4;
IOBUF PORT "gpdi_dp[1]" IO_TYPE=LVCMOS33D DRIVE=4;
IOBUF PORT "gpdi_dn[1]" IO_TYPE=LVCMOS33D DRIVE=4;
IOBUF PORT "gpdi_dp[2]" IO_TYPE=LVCMOS33D DRIVE=4;
IOBUF PORT "gpdi_dn[2]" IO_TYPE=LVCMOS33D DRIVE=4;
IOBUF PORT "gpdi_dp[3]" IO_TYPE=LVCMOS33D DRIVE=4;
IOBUF PORT "gpdi_dn[3]" IO_TYPE=LVCMOS33D DRIVE=4;
IOBUF PORT "gpdi_util" IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gpdi_hpd" IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gpdi_cec" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gpdi_sda" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gpdi_scl" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
# GPIO (default single-ended) "gpio", "ram", "gpdi" sheet
# Pins enumerated gp[0-27], gn[0-27].
# With differential mode enabled on Lattice,
# gp[] (+) are used, gn[] (-) are ignored from design
# as they handle inverted signal by default.
# To enable differential, rename LVCMOS33->LVCMOS33D
# FEMALE ANGLED (90 deg PMOD) on TOP or
# MALE VERTICAL ( 0 deg pins) on BOTTOM and flat cable
LOCATE COMP "gp[0]" SITE "B11"; # PCLK
LOCATE COMP "gn[0]" SITE "C11"; # PCLK
LOCATE COMP "gp[1]" SITE "A10"; # PCLK
LOCATE COMP "gn[1]" SITE "A11"; # PCLK
LOCATE COMP "gp[2]" SITE "A9"; # GR_PCLK
LOCATE COMP "gn[2]" SITE "B10"; # GR_PCLK
LOCATE COMP "gp[3]" SITE "B9";
LOCATE COMP "gn[3]" SITE "C10";
LOCATE COMP "gp[4]" SITE "A7";
LOCATE COMP "gn[4]" SITE "A8";
LOCATE COMP "gp[5]" SITE "C8";
LOCATE COMP "gn[5]" SITE "B8";
LOCATE COMP "gp[6]" SITE "C6";
LOCATE COMP "gn[6]" SITE "C7";
IOBUF PORT "gp[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[2]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[2]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[4]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[4]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[5]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[5]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[6]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[6]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
LOCATE COMP "gp[7]" SITE "A6";
LOCATE COMP "gn[7]" SITE "B6";
LOCATE COMP "gp[8]" SITE "A4"; # DIFF
LOCATE COMP "gn[8]" SITE "A5"; # DIFF
LOCATE COMP "gp[9]" SITE "A2"; # DIFF
LOCATE COMP "gn[9]" SITE "B1"; # DIFF
LOCATE COMP "gp[10]" SITE "C4"; # DIFF
LOCATE COMP "gn[10]" SITE "B4"; # DIFF
LOCATE COMP "gp[11]" SITE "F4"; # DIFF wifi_gpio26
LOCATE COMP "gn[11]" SITE "E3"; # DIFF wifi_gpio25
LOCATE COMP "gp[12]" SITE "G3"; # DIFF wifi_gpio33 PCLK
LOCATE COMP "gn[12]" SITE "F3"; # DIFF wifi_gpio32 PCLK
LOCATE COMP "gp[13]" SITE "H4"; # DIFF wifi_gpio35
LOCATE COMP "gn[13]" SITE "G5"; # DIFF wifi_gpio34
IOBUF PORT "gp[7]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[7]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[8]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[8]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[9]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[9]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[10]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[10]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[11]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[11]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[12]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[12]" PULLMODE=NONE IO_TYPE=LVCMOS33;
FREQUENCY PORT "gn[12]" 50 MHZ;
IOBUF PORT "gp[13]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[13]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
LOCATE COMP "gp[14]" SITE "U18"; # DIFF ADC AIN1
LOCATE COMP "gn[14]" SITE "U17"; # DIFF ADC AIN0
LOCATE COMP "gp[15]" SITE "N17"; # DIFF ADC AIN3
LOCATE COMP "gn[15]" SITE "P16"; # DIFF ADC AIN2
LOCATE COMP "gp[16]" SITE "N16"; # DIFF ADC AIN5
LOCATE COMP "gn[16]" SITE "M17"; # DIFF ADC AIN4
LOCATE COMP "gp[17]" SITE "L16"; # DIFF ADC AIN7 GR_PCLK
LOCATE COMP "gn[17]" SITE "L17"; # DIFF ADC AIN6
LOCATE COMP "gp[18]" SITE "H18"; # DIFF
LOCATE COMP "gn[18]" SITE "H17"; # DIFF
LOCATE COMP "gp[19]" SITE "F17"; # DIFF
LOCATE COMP "gn[19]" SITE "G18"; # DIFF
LOCATE COMP "gp[20]" SITE "D18"; # DIFF
LOCATE COMP "gn[20]" SITE "E17"; # DIFF
IOBUF PORT "gp[14]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[14]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[15]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[15]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[16]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[16]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[17]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[17]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[18]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[18]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[19]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[19]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[20]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[20]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
LOCATE COMP "gp[21]" SITE "C18"; # DIFF
LOCATE COMP "gn[21]" SITE "D17"; # DIFF
LOCATE COMP "gp[22]" SITE "B15";
LOCATE COMP "gn[22]" SITE "C15";
LOCATE COMP "gp[23]" SITE "B17";
LOCATE COMP "gn[23]" SITE "C17";
LOCATE COMP "gp[24]" SITE "C16";
LOCATE COMP "gn[24]" SITE "D16";
LOCATE COMP "gp[25]" SITE "D14";
LOCATE COMP "gn[25]" SITE "E14";
LOCATE COMP "gp[26]" SITE "B13";
LOCATE COMP "gn[26]" SITE "C13";
LOCATE COMP "gp[27]" SITE "D13";
LOCATE COMP "gn[27]" SITE "E13";
IOBUF PORT "gp[21]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[21]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[22]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[22]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[23]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[23]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[24]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[24]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[25]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[25]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[26]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[26]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp[27]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn[27]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
## GPIO repeated as individual signals (non-vector)
# Allows mixed input, output, bidirectional, clock, differential
# If any of individual gp is used, then don't use gp[] vector.
# Same for gn and gn[].
# FEMALE ANGLED (90 deg PMOD) on TOP or
# MALE VERTICAL ( 0 deg pins) on BOTTOM and flat cable
LOCATE COMP "gp0" SITE "B11"; # PCLK
LOCATE COMP "gn0" SITE "C11"; # PCLK
LOCATE COMP "gp1" SITE "A10"; # PCLK
LOCATE COMP "gn1" SITE "A11"; # PCLK
LOCATE COMP "gp2" SITE "A9"; # GR_PCLK
LOCATE COMP "gn2" SITE "B10"; # GR_PCLK
LOCATE COMP "gp3" SITE "B9";
LOCATE COMP "gn3" SITE "C10";
LOCATE COMP "gp4" SITE "A7";
LOCATE COMP "gn4" SITE "A8";
LOCATE COMP "gp5" SITE "C8";
LOCATE COMP "gn5" SITE "B8";
LOCATE COMP "gp6" SITE "C6";
LOCATE COMP "gn6" SITE "C7";
IOBUF PORT "gp0" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn0" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp1" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn1" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp2" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn2" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp3" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn3" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp4" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn4" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp5" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn5" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp6" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn6" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
LOCATE COMP "gp7" SITE "A6";
LOCATE COMP "gn7" SITE "B6";
LOCATE COMP "gp8" SITE "A4"; # DIFF
LOCATE COMP "gn8" SITE "A5"; # DIFF
LOCATE COMP "gp9" SITE "A2"; # DIFF
LOCATE COMP "gn9" SITE "B1"; # DIFF
LOCATE COMP "gp10" SITE "C4"; # DIFF
LOCATE COMP "gn10" SITE "B4"; # DIFF
LOCATE COMP "gp11" SITE "F4"; # DIFF wifi_gpio26
LOCATE COMP "gn11" SITE "E3"; # DIFF wifi_gpio25
LOCATE COMP "gp12" SITE "G3"; # DIFF wifi_gpio33 PCLK
LOCATE COMP "gn12" SITE "F3"; # DIFF wifi_gpio32 PCLK
LOCATE COMP "gp13" SITE "H4"; # DIFF wifi_gpio35
LOCATE COMP "gn13" SITE "G5"; # DIFF wifi_gpio34
# wifi sharing PCB v2.0.6-v3.0.8
# prior to v2.0.6 see schematics
IOBUF PORT "gp7" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn7" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp8" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn8" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp9" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn9" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp10" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn10" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp11" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn11" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp12" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn12" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
FREQUENCY PORT "gn12" 50 MHZ;
IOBUF PORT "gp13" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn13" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
LOCATE COMP "gp14" SITE "U18"; # DIFF ADC AIN1
LOCATE COMP "gn14" SITE "U17"; # DIFF ADC AIN0
LOCATE COMP "gp15" SITE "N17"; # DIFF ADC AIN3
LOCATE COMP "gn15" SITE "P16"; # DIFF ADC AIN2
LOCATE COMP "gp16" SITE "N16"; # DIFF ADC AIN5
LOCATE COMP "gn16" SITE "M17"; # DIFF ADC AIN4
LOCATE COMP "gp17" SITE "L16"; # DIFF ADC AIN7 GR_PCLK
LOCATE COMP "gn17" SITE "L17"; # DIFF ADC AIN6
LOCATE COMP "gp18" SITE "H18"; # DIFF
LOCATE COMP "gn18" SITE "H17"; # DIFF
LOCATE COMP "gp19" SITE "F17"; # DIFF
LOCATE COMP "gn19" SITE "G18"; # DIFF
LOCATE COMP "gp20" SITE "D18"; # DIFF
LOCATE COMP "gn20" SITE "E17"; # DIFF
IOBUF PORT "gp14" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn14" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp15" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn15" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp16" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn16" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp17" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn17" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp18" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn18" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp19" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn19" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp20" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn20" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
LOCATE COMP "gp21" SITE "C18"; # DIFF
LOCATE COMP "gn21" SITE "D17"; # DIFF
LOCATE COMP "gp22" SITE "B15";
LOCATE COMP "gn22" SITE "C15";
LOCATE COMP "gp23" SITE "B17";
LOCATE COMP "gn23" SITE "C17";
LOCATE COMP "gp24" SITE "C16";
LOCATE COMP "gn24" SITE "D16";
LOCATE COMP "gp25" SITE "D14";
LOCATE COMP "gn25" SITE "E14";
LOCATE COMP "gp26" SITE "B13";
LOCATE COMP "gn26" SITE "C13";
LOCATE COMP "gp27" SITE "D13";
LOCATE COMP "gn27" SITE "E13";
IOBUF PORT "gp21" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn21" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp22" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn22" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp23" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn23" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp24" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn24" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp25" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn25" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp26" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn26" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gp27" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "gn27" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
## PROGRAMN (reload bitstream from FLASH, exit from bootloader)
# PCB v2.0.5 and higher
LOCATE COMP "user_programn" SITE "M4";
IOBUF PORT "user_programn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
## SHUTDOWN "power", "ram" sheet (connected from PCB v1.7.5)
# on PCB v1.7 shutdown is not connected to FPGA
LOCATE COMP "shutdown" SITE "G16"; # FPGA receives
IOBUF PORT "shutdown" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;

View File

@ -0,0 +1,36 @@
## UART (uart0)
set_io uart_txd_o 38
set_io uart_rxd_i 28
## SPI - on-board flash
set_io flash_sdo_o 14
set_io flash_sck_o 15
set_io flash_csn_o 16
set_io flash_sdi_i 17
## SPI - user port
set_io spi_sdo_o 34
set_io spi_sck_o 43
set_io spi_csn_o 36
set_io spi_sdi_i 42
## TWI
set_io twi_sda_io 31
set_io twi_scl_io 37
## GPIO - input
set_io gpio_i[0] 44
set_io gpio_i[1] 4
set_io gpio_i[2] 3
set_io gpio_i[3] 48
## GPIO - output
set_io gpio_o[0] 45
set_io gpio_o[1] 47
set_io gpio_o[2] 46
set_io gpio_o[3] 2
## RGB power LED
set_io pwm_o[0] 39
set_io pwm_o[1] 40
set_io pwm_o[2] 41

View File

@ -0,0 +1,39 @@
## UART (uart0)
set_io uart_txd_o 9
set_io uart_rxd_i 6
## SPI - on-board flash
set_io flash_sdo_o 14
set_io flash_sck_o 15
set_io flash_csn_o 16
set_io flash_sdi_i 17
## SPI - user port
set_io spi_sdo_o 43
set_io spi_sck_o 38
set_io spi_csn_o 34
set_io spi_sdi_i 31
## TWI
set_io twi_sda_io 2
set_io twi_scl_io 4
## GPIO - input
set_io gpio_i[0] 18
set_io gpio_i[1] 19
set_io gpio_i[2] 20
set_io gpio_i[3] 28
## GPIO - output
set_io gpio_o[0] 25
set_io gpio_o[1] 26
set_io gpio_o[2] 27
set_io gpio_o[3] 23
## RGB power LED
set_io pwm_o[0] 39
set_io pwm_o[1] 40
set_io pwm_o[2] 41
#User Reset Btn
set_io user_reset_btn 10

View File

@ -0,0 +1,69 @@
#| iCESugar-v1.5
#> Clock (12 MHz)
set_io --warn-no-port iCESugarv15_CLK 35
#> Tri-colour LED
set_io --warn-no-port iCESugarv15_LED_G 41
set_io --warn-no-port iCESugarv15_LED_R 40
set_io --warn-no-port iCESugarv15_LED_B 39
#> UART
set_io --warn-no-port iCESugarv15_RX 4
set_io --warn-no-port iCESugarv15_TX 6
#> USB
set_io --warn-no-port iCESugarv15_USB_DN 9
set_io --warn-no-port iCESugarv15_USB_DP 10
set_io --warn-no-port iCESugarv15_USB_DP_PU 11
#> PMOD 1
set_io --warn-no-port iCESugarv15_PMOD1A_0 10
set_io --warn-no-port iCESugarv15_PMOD1A_1 6
set_io --warn-no-port iCESugarv15_PMOD1A_2 3
set_io --warn-no-port iCESugarv15_PMOD1A_3 48
set_io --warn-no-port iCESugarv15_PMOD1B_0 47
set_io --warn-no-port iCESugarv15_PMOD1B_1 2
set_io --warn-no-port iCESugarv15_PMOD1B_2 4
set_io --warn-no-port iCESugarv15_PMOD1B_3 9
#> PMOD 2
set_io --warn-no-port iCESugarv15_PMOD2A_0 46
set_io --warn-no-port iCESugarv15_PMOD2A_1 44
set_io --warn-no-port iCESugarv15_PMOD2A_2 42
set_io --warn-no-port iCESugarv15_PMOD2A_3 37
set_io --warn-no-port iCESugarv15_PMOD2B_0 36
set_io --warn-no-port iCESugarv15_PMOD2B_1 38
set_io --warn-no-port iCESugarv15_PMOD2B_2 43
set_io --warn-no-port iCESugarv15_PMOD2B_3 45
#> PMOD 3
set_io --warn-no-port iCESugarv15_PMOD3A_0 34
set_io --warn-no-port iCESugarv15_PMOD3A_1 31
set_io --warn-no-port iCESugarv15_PMOD3A_2 27
set_io --warn-no-port iCESugarv15_PMOD3A_3 25
set_io --warn-no-port iCESugarv15_PMOD3B_0 23
set_io --warn-no-port iCESugarv15_PMOD3B_1 26
set_io --warn-no-port iCESugarv15_PMOD3B_2 28
set_io --warn-no-port iCESugarv15_PMOD3B_3 32
#> PMOD 4 | Switches
set_io --warn-no-port iCESugarv15_PMOD4_0 21
set_io --warn-no-port iCESugarv15_PMOD4_1 20
set_io --warn-no-port iCESugarv15_PMOD4_2 19
set_io --warn-no-port iCESugarv15_PMOD4_3 18
#> SPI
set_io --warn-no-port iCESugarv15_SPI_SS 16
set_io --warn-no-port iCESugarv15_SPI_SCK 15
set_io --warn-no-port iCESugarv15_SPI_MOSI 17
set_io --warn-no-port iCESugarv15_SPI_MISO 14

View File

@ -0,0 +1,75 @@
library ieee ;
use ieee.std_logic_1164.all;
package components is
-- Yosys wrapper components
component EHXPLLL
generic
(
CLKI_DIV : integer := 1;
CLKFB_DIV : integer := 1;
CLKOP_DIV : integer := 8;
CLKOS_DIV : integer := 8;
CLKOS2_DIV : integer := 8;
CLKOS3_DIV : integer := 8;
CLKOP_ENABLE : string := "ENABLED";
CLKOS_ENABLE : string := "DISABLED";
CLKOS2_ENABLE : string := "DISABLED";
CLKOS3_ENABLE : string := "DISABLED";
CLKOP_CPHASE : integer := 0;
CLKOS_CPHASE : integer := 0;
CLKOS2_CPHASE : integer := 0;
CLKOS3_CPHASE : integer := 0;
CLKOP_FPHASE : integer := 0;
CLKOS_FPHASE : integer := 0;
CLKOS2_FPHASE : integer := 0;
CLKOS3_FPHASE : integer := 0;
FEEDBK_PATH : string := "CLKOP";
CLKOP_TRIM_POL : string := "RISING";
CLKOP_TRIM_DELAY : integer := 0;
CLKOS_TRIM_POL : string := "RISING";
CLKOS_TRIM_DELAY : integer := 0;
OUTDIVIDER_MUXA : string := "DIVA";
OUTDIVIDER_MUXB : string := "DIVB";
OUTDIVIDER_MUXC : string := "DIVC";
OUTDIVIDER_MUXD : string := "DIVD";
PLL_LOCK_MODE : integer := 0;
PLL_LOCK_DELAY : integer := 200;
STDBY_ENABLE : string := "DISABLED";
REFIN_RESET : string := "DISABLED";
SYNC_ENABLE : string := "DISABLED";
INT_LOCK_STICKY : string := "ENABLED";
DPHASE_SOURCE : string := "DISABLED";
PLLRST_ENA : string := "DISABLED";
INTFB_WAKE : string := "DISABLED"
);
port
(
CLKI : IN std_logic := 'X';
CLKFB : IN std_logic := 'X';
RST : IN std_logic := 'X';
STDBY : IN std_logic := 'X';
PLLWAKESYNC : IN std_logic := 'X';
PHASESEL1 : IN std_logic := 'X';
PHASESEL0 : IN std_logic := 'X';
PHASEDIR : IN std_logic := 'X';
PHASESTEP : IN std_logic := 'X';
PHASELOADREG : IN std_logic := 'X';
ENCLKOP : IN std_logic := 'X';
ENCLKOS : IN std_logic := 'X';
ENCLKOS2 : IN std_logic := 'X';
ENCLKOS3 : IN std_logic := 'X';
CLKOP : OUT std_logic := 'X';
CLKOS : OUT std_logic := 'X';
CLKOS2 : OUT std_logic := 'X';
CLKOS3 : OUT std_logic := 'X';
LOCK : OUT std_logic := 'X';
INTLOCK : OUT std_logic := 'X';
REFCLK : OUT std_logic := 'X';
CLKINTFB : OUT std_logic := 'X'
);
end component;
end package;

View File

@ -0,0 +1,145 @@
-- #################################################################################################
-- # << NEORV32 - Processor-Internal DMEM for Lattice iCE40 UltraPlus >> #
-- # ********************************************************************************************* #
-- # Memory has a physical size of 64kb (2 x SPRAMs). #
-- # Logical size DMEM_SIZE must be less or equal. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
library iCE40;
use iCE40.components.all;
architecture neorv32_dmem_rtl of neorv32_dmem is
-- advanced configuration --------------------------------------------------------------------------------
constant spram_sleep_mode_en_c : boolean := false; -- put DMEM into sleep mode when idle (for low power)
-- -------------------------------------------------------------------------------------------------------
-- IO space: module base address --
constant hi_abb_c : natural := 31; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(64*1024); -- low address boundary bit
-- local signals --
signal acc_en : std_ulogic;
signal mem_cs : std_ulogic;
signal rdata : std_ulogic_vector(31 downto 0);
signal rden : std_ulogic;
-- SPRAM signals --
signal spram_clk : std_logic;
signal spram_addr : std_logic_vector(13 downto 0);
signal spram_di_lo : std_logic_vector(15 downto 0);
signal spram_di_hi : std_logic_vector(15 downto 0);
signal spram_do_lo : std_logic_vector(15 downto 0);
signal spram_do_hi : std_logic_vector(15 downto 0);
signal spram_be_lo : std_logic_vector(03 downto 0);
signal spram_be_hi : std_logic_vector(03 downto 0);
signal spram_we : std_logic;
signal spram_pwr_n : std_logic;
signal spram_cs : std_logic;
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using iCE40up SPRAM-based DMEM." severity note;
assert not (DMEM_SIZE > 64*1024) report "NEORV32 PROCESSOR CONFIG ERROR: DMEM has a fixed physical size of 64kB. Logical size must be less or equal." severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = DMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
mem_cs <= acc_en and (rden_i or wren_i);
-- Memory Access --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
imem_spram_lo_inst : SB_SPRAM256KA
port map (
ADDRESS => spram_addr, -- I
DATAIN => spram_di_lo, -- I
MASKWREN => spram_be_lo, -- I
WREN => spram_we, -- I
CHIPSELECT => spram_cs, -- I
CLOCK => spram_clk, -- I
STANDBY => '0', -- I
SLEEP => spram_pwr_n, -- I
POWEROFF => '1', -- I
DATAOUT => spram_do_lo -- O
);
imem_spram_hi_inst : SB_SPRAM256KA
port map (
ADDRESS => spram_addr, -- I
DATAIN => spram_di_hi, -- I
MASKWREN => spram_be_hi, -- I
WREN => spram_we, -- I
CHIPSELECT => spram_cs, -- I
CLOCK => spram_clk, -- I
STANDBY => '0', -- I
SLEEP => spram_pwr_n, -- I
POWEROFF => '1', -- I
DATAOUT => spram_do_hi -- O
);
-- access logic and signal type conversion --
spram_clk <= std_logic(clk_i);
spram_addr <= std_logic_vector(addr_i(13+2 downto 0+2));
spram_di_lo <= std_logic_vector(data_i(15 downto 00));
spram_di_hi <= std_logic_vector(data_i(31 downto 16));
spram_we <= '1' when ((acc_en and wren_i) = '1') else '0'; -- global write enable
spram_cs <= std_logic(mem_cs);
spram_be_lo <= std_logic(ben_i(1)) & std_logic(ben_i(1)) & std_logic(ben_i(0)) & std_logic(ben_i(0)); -- low byte write enable
spram_be_hi <= std_logic(ben_i(3)) & std_logic(ben_i(3)) & std_logic(ben_i(2)) & std_logic(ben_i(2)); -- high byte write enable
spram_pwr_n <= '0' when ((spram_sleep_mode_en_c = false) or (mem_cs = '1')) else '1'; -- LP mode disabled or IMEM selected
rdata <= std_ulogic_vector(spram_do_hi) & std_ulogic_vector(spram_do_lo);
buffer_ff: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= mem_cs;
rden <= acc_en and rden_i;
end if;
end process buffer_ff;
-- output gate --
data_o <= rdata when (rden = '1') else (others => '0');
end neorv32_dmem_rtl;

View File

@ -0,0 +1,146 @@
-- #################################################################################################
-- # << NEORV32 - Processor-Internal IMEM for Lattice iCE40 UltraPlus >> #
-- # ********************************************************************************************* #
-- # Memory has a physical size of 64kb (2 x SPRAMs). #
-- # Logical size IMEM_SIZE must be less or equal. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, 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;
library iCE40;
use iCE40.components.all;
architecture neorv32_imem_rtl of neorv32_imem is
-- advanced configuration --------------------------------------------------------------------------------
constant spram_sleep_mode_en_c : boolean := false; -- put IMEM into sleep mode when idle (for low power)
-- -------------------------------------------------------------------------------------------------------
-- IO space: module base address --
constant hi_abb_c : natural := 31; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(64*1024); -- low address boundary bit
-- local signals --
signal acc_en : std_ulogic;
signal mem_cs : std_ulogic;
signal rdata : std_ulogic_vector(31 downto 0);
signal rden : std_ulogic;
-- SPRAM signals --
signal spram_clk : std_logic;
signal spram_addr : std_logic_vector(13 downto 0);
signal spram_di_lo : std_logic_vector(15 downto 0);
signal spram_di_hi : std_logic_vector(15 downto 0);
signal spram_do_lo : std_logic_vector(15 downto 0);
signal spram_do_hi : std_logic_vector(15 downto 0);
signal spram_be_lo : std_logic_vector(03 downto 0);
signal spram_be_hi : std_logic_vector(03 downto 0);
signal spram_we : std_logic;
signal spram_pwr_n : std_logic;
signal spram_cs : std_logic;
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report "NEORV32 PROCESSOR CONFIG NOTE: Using iCE40up SPRAM-based IMEM." severity note;
assert not (IMEM_AS_IROM = true) report "NEORV32 PROCESSOR CONFIG ERROR: ICE40 Ultra Plus SPRAM cannot be initialized by bitstream!" severity failure;
assert not (IMEM_SIZE > 64*1024) report "NEORV32 PROCESSOR CONFIG ERROR: IMEM has a fixed physical size of 64kB. Logical size must be less or equal." severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = IMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
mem_cs <= acc_en and (rden_i or wren_i);
-- Memory Access --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
imem_spram_lo_inst : SB_SPRAM256KA
port map (
ADDRESS => spram_addr, -- I
DATAIN => spram_di_lo, -- I
MASKWREN => spram_be_lo, -- I
WREN => spram_we, -- I
CHIPSELECT => spram_cs, -- I
CLOCK => spram_clk, -- I
STANDBY => '0', -- I
SLEEP => spram_pwr_n, -- I
POWEROFF => '1', -- I
DATAOUT => spram_do_lo -- O
);
imem_spram_hi_inst : SB_SPRAM256KA
port map (
ADDRESS => spram_addr, -- I
DATAIN => spram_di_hi, -- I
MASKWREN => spram_be_hi, -- I
WREN => spram_we, -- I
CHIPSELECT => spram_cs, -- I
CLOCK => spram_clk, -- I
STANDBY => '0', -- I
SLEEP => spram_pwr_n, -- I
POWEROFF => '1', -- I
DATAOUT => spram_do_hi -- O
);
-- access logic and signal type conversion --
spram_clk <= std_logic(clk_i);
spram_addr <= std_logic_vector(addr_i(13+2 downto 0+2));
spram_di_lo <= std_logic_vector(data_i(15 downto 00));
spram_di_hi <= std_logic_vector(data_i(31 downto 16));
spram_we <= '1' when ((acc_en and wren_i) = '1') else '0'; -- global write enable
spram_cs <= std_logic(mem_cs);
spram_be_lo <= std_logic(ben_i(1)) & std_logic(ben_i(1)) & std_logic(ben_i(0)) & std_logic(ben_i(0)); -- low byte write enable
spram_be_hi <= std_logic(ben_i(3)) & std_logic(ben_i(3)) & std_logic(ben_i(2)) & std_logic(ben_i(2)); -- high byte write enable
spram_pwr_n <= '0' when ((spram_sleep_mode_en_c = false) or (mem_cs = '1')) else '1'; -- LP mode disabled or IMEM selected
rdata <= std_ulogic_vector(spram_do_hi) & std_ulogic_vector(spram_do_lo);
buffer_ff: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= mem_cs;
rden <= acc_en and rden_i;
end if;
end process buffer_ff;
-- output gate --
data_o <= rdata when (rden = '1') else (others => '0');
end neorv32_imem_rtl;

Some files were not shown because too many files have changed in this diff Show More