Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[proposal] add rtl/test_setups #136

Merged
merged 13 commits into from
Aug 14, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/datasheet/overview.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ neorv32 - Project home folder
│├core - Core sources of the CPU & SoC
│└templates - Alternate/additional top entities & wrappers
│ ├processor - Processor SoC wrappers
│ └system - System wrappers for advanced connectivity
│ ├system - System wrappers for advanced connectivity
│ └test_setups - Minimal test setup "SoCs" used in the User Guide
├setups - Example setups for various FPGAs, boards and toolchains
│└...
Expand Down
167 changes: 92 additions & 75 deletions docs/userguide/content.adoc
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
Let's Get It Started!

To make your NEORV32 project run, follow the guides from the upcoming sections. Follow these guides
step by step and in the presented order.
This user guide uses the NEORV32 project _as is_ from the official `neorv32` repository.
To make your first NEORV32 project run, follow the guides from the upcoming sections. It is recommended to
follow these guides step by step and eventually in the presented order.

[TIP]
This guide uses the minimalistic and platform/toolchain agnostic SoC test setups from
`rtl/test_setups` for illustration. You can use one of the provided test setups for
your first FPGA tests. Alternatively, have a look at the `setups` folder,
which provides more sophisticated example setups for various FPGAs/FPGA boards and toolchains.


:sectnums:
== Software Toolchain Setup

To compile (and debug) executables for the NEORV32 a RISC-V toolchain is required.
There are two possibilities to get this:

1. Download and _build_ the official RISC-V GNU toolchain yourself
1. Download and _build_ the official RISC-V GNU toolchain yourself.
2. Download and install a prebuilt version of the toolchain; this might also done via the package manager / app store of your OS

[TIP]
The default toolchain prefix for this project is **`riscv32-unknown-elf-`**. Of course you can use any other RISC-V
toolchain (like `riscv64-unknown-elf-`) that is capable to emit code for a `rv32` architecture. Just change the _RISCV_PREFIX_ variable in the application
makefile(s) according to your needs or define this variable when invoking the makefile.

[IMPORTANT]
Keep in mind that – for instance – a rv32imc toolchain only provides library code compiled with
compressed (_C_) and `mul`/`div` instructions (_M_)! Hence, this code cannot be executed (without
emulation) on an architecture without these extensions!
[NOTE]
The default toolchain prefix (`RISCV_PREFIX` variable) for this project is **`riscv32-unknown-elf-`**. Of course you can use any other RISC-V
toolchain (like `riscv64-unknown-elf-`) that is capable to emit code for a `rv32` architecture. Just change `RISCV_PREFIX`
according to your needs.


:sectnums:
Expand All @@ -39,6 +42,11 @@ riscv-gnu-toolchain$ ./configure --prefix=/opt/riscv --with-arch=rv32i –-with-
riscv-gnu-toolchain$ make
----

[IMPORTANT]
Keep in mind that – for instance – a toolchain build with `--with-arch=rv32imc` only provides library code compiled with
compressed (`C`) and `mul`/`div` instructions (`M`)! Hence, this code cannot be executed (without
emulation) on an architecture without these extensions!


:sectnums:
=== Downloading and Installing a Prebuilt Toolchain
Expand Down Expand Up @@ -103,114 +111,123 @@ Everything is working fine if `Toolchain check OK` appears at the end.
:sectnums:
== General Hardware Setup

This guide will setup a NEORV32 project for FPGA implementation (or simulation only) _from scratch_
This guide shows the basics of setting up a NEORV32 project for FPGA implementation (or simulation only)
_from scratch_. It uses a _simplified_ test "SoC" setup of the processor to keeps things simple at the beginning.
This simple setup is intended for evaluation or as "hello world" project to check out the NEORV32
on _your_ FPGA board.

[TIP]
If you want to use a complete pre-defined setup to start with, check out the
project's `setups` folder (https://github.com/stnolting/neorv32/tree/master/setups),
which provides (script-based) demo setups for various FPGA boards and toolchains.
If you want to use a more sophisticated pre-defined setup to start with, check out the
`setups` folder, which provides example setups for various FPGA, boards and toolchains.

The NEORV32 project features two minimalistic pre-built test setups. Both test setups only implements
some very basic processor and CPU features.
The main difference is the processor boot concept - so how to get a software executable
into the processor:

* **`rtl/test_setups/neorv32_testsetup_approm.vhd`**: this setup does not require a connection via UART. The
software executable is "installed" into the bitstream to initialize a read-only memory. Use this setup
if your FPGA board does not provide a UART interface.
* **`rtl/test_setups/neorv32_testsetup_bootloader.vhd`**: this setups uses the UART and the default NEORV32
bootloader to upload new software executables. Use this setup if your board provides a UART interface.

This tutorial uses a _simplified_ test setup of the processor
to keeps things simple at the beginning as this setup is intended as
evaluation or "hello world" project to check out the NEORV32.
.NEORV32 "hello world" test setup (`rtl/test_setups/neorv32_testsetup_bootloader.vhd`)
image::neorv32_test_setup.png[align=center]

[start=1]
. Create a new project with your FPGA EDA tool of choice.
. Add all VHDL files from the project's `rtl/core` folder to your project. Make sure to _reference_ the
files only – do not copy them.
. Add all VHDL files from the project's `rtl/core` folder to your project.
. Make sure to add all the rtl files to a new library called `neorv32`. If your FPGA tools does not
provide a field to enter the library name, check out the "properties" menu of the added rtl files.
. The `rtl/core/neorv32_top.vhd` VHDL file is the top entity of the NEORV32 processor. If you
already have a design, instantiate this unit into your design and proceed.
. The `rtl/core/neorv32_top.vhd` VHDL file is the top entity of the NEORV32 processor, which can be
instantiated into the "real" project. However, in this tutorial we will use one of the pre-defined
test setups from `rtl/test_setups` (see above).

[IMPORTANT]
Make sure to include the `neorv32` package into your design when instantiating the processor: add
`library neorv32;` and `use neorv32.neorv32_package.all;` to your design unit.

[start=5]
. If you do not have a design yet and just want to check out the NEORV32 – no problem! This guide
uses a simplified top entity, that encapsulates the actual processor top entity: add the
`rtl/templates/processor/neorv32_ProcessorTop_Test.vhd` VHDL file to your project, too, and
select it as _top entity_.
. This test setup provides a minimal test hardware setup:

.NEORV32 "hello world" test setup
image::neorv32_test_setup.png[align=center]
. Add the pre-defined test setup of choice to the project, too, and select it as _top entity_.
stnolting marked this conversation as resolved.
Show resolved Hide resolved
. The entity of both test setups
provide a minimal set of configuration generics, that might have to be adapted to match your FPGA and board:

[start=7]
. It only implements some very basic processor and CPU features. Also, only the
minimum number of signals is propagated to the outer world.
. However, a minimal setup-specific configuration of the NEORV32 processor is required to make it run
on your FPGA board of choice. Only the absolutely required modifications will be made while
keeping the default configuration for the remaining configuration options:

.Cut-out of `neorv32_ProcessorTop_Test.vhd` showing the processor instance and its configuration
.Test setup entity - configuration generics
[source,vhdl]
----
neorv32_top_inst: neorv32_top
generic map (
-- General --
CLOCK_FREQUENCY => 100000000, -- in Hz # <1>
INT_BOOTLOADER_EN => true,
...
-- Internal instruction memory --
MEM_INT_IMEM_EN => true,
MEM_INT_IMEM_SIZE => 16*1024, # <2>
-- Internal data memory --
MEM_INT_DMEM_EN => true,
MEM_INT_DMEM_SIZE => 8*1024, # <3>
...
generic (
-- adapt these for your setup --
CLOCK_FREQUENCY : natural := 100000000; <1>
MEM_INT_IMEM_SIZE : natural := 16*1024; <2>
MEM_INT_DMEM_SIZE : natural := 8*1024 <3>
);
----
<1> Clock frequency of `clk_i` signal in Hertz
<2> Default size of internal instruction memory: 16kB
<3> Default size of internal data memory: 8kB

[start=9]
. There is one generic that has to be set according to your FPGA board setup: the actual clock frequency
of the top's clock input signal (`clk_i`). Use the _CLOCK_FREQUENC_Y generic to specify your clock source's
frequency in Hertz (Hz) (note "1").
. If you feel like it – or if your FPGA does not provide many resources – you can modify the
**memory sizes** (_MEM_INT_IMEM_SIZE_ and _MEM_INT_DMEM_SIZE_ – marked with notes "2" and "3") or even
exclude certain ISA extensions and peripheral modules from implementation - but as mentioned above, let's keep things
simple at first and use the standard configuration for now.
[start=7]
. If you feel like it – or if your FPGA does not provide sufficient resources – you can modify the
_memory sizes_ (`MEM_INT_IMEM_SIZE` and `MEM_INT_DMEM_SIZE` – marked with notes "2" and "3"). But as mentioned
above, let's keep things simple at first and use the standard configuration for now.
. There is one generic that _has to be set according to your FPGA board_ setup: the actual clock frequency
stnolting marked this conversation as resolved.
Show resolved Hide resolved
of the top's clock input signal (`clk_i`). Use the `CLOCK_FREQUENCY` generic to specify your clock source's
frequency in Hertz (Hz).

[NOTE]
If you have changed the default memory configuration (_MEM_INT_IMEM_SIZE_ and _MEM_INT_DMEM_SIZE_ generics)
If you have changed the default memory configuration (`MEM_INT_IMEM_SIZE` and `MEM_INT_DMEM_SIZE` generics)
keep those new sizes in mind – these values are required for setting
up the software framework in the next section <<_general_software_framework_setup>>.

[start=11]
[start=9]
. Depending on your FPGA tool of choice, it is time to assign the signals of the test setup top entity to
the according pins of your FPGA board. All the signals can be found in the entity declaration:
the according pins of your FPGA board. All the signals can be found in the entity declaration of the
stnolting marked this conversation as resolved.
Show resolved Hide resolved
corresponding test setup:

.Entity signals of `neorv32_testsetup_approm.vhd`
[source,vhdl]
----
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
);
----

.Entity signals of `neorv32_test_setup.vhd`
.Entity signals of `neorv32_testsetup_bootloader.vhd`
[source,vhdl]
----
entity neorv32_test_setup is
port (
-- Global control --
clk_i : in std_ulogic := '0'; -- global clock, rising edge
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
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 := '0' -- UART0 receive data
);
end neorv32_test_setup;
uart0_rxd_i : in std_ulogic -- UART0 receive data
);
----

[start=12]
[start=10]
. Attach the clock input `clk_i` to your clock source and connect the reset line `rstn_i` to a button of
your FPGA board. Check whether it is low-active or high-active – the reset signal of the processor is
**low-active**, so maybe you need to invert the input signal.
. If possible, connected at least bit `0` of the GPIO output port `gpio_o` to a high-active LED (invert
the signal when your LEDs are low-active). This LED will be used as status LED for the setup.
. Finally, if your FPGA board provides a serial host interface (USB-to-serial converter) interface,
connect the UART communication signals `uart0_txd_o` and `uart0_rxd_i`.
the signal when your LEDs are low-active).
stnolting marked this conversation as resolved.
Show resolved Hide resolved
. Finally, if your are using the UART-based test setup (`neorv32_testsetup_bootloader.vhd`)
connect the UART communication signals `uart0_txd_o` and `uart0_rxd_i` to the host interface (e.g. USB-UART converter).
. Perform the project HDL compilation (synthesis, mapping, bitstream generation).
. Program the generated bitstream into your FPGA and press the button connected to the reset signal.
. Done! The assigned status LED should be flashing now for some sections before permanently lighting up.
. Done! The LED at `gpio_o(0)` should be flashing now.

[TIP]
After the GCC toolchain for compiling RISC-V source code is ready (chapter <<_general_software_framework_setup>>),
you can advance to one of these chapters to learn how to get a software executable into your processor setup:
* If you are using the `neorv32_testsetup_approm.vhd` setup: See section <<_installing_an_executable_directly_into_memory>>.
* If you are using the `neorv32_testsetup_bootloader.vhd` setup: See section <<_uploading_and_starting_of_a_binary_executable_image_via_uart>>.



Expand Down
10 changes: 10 additions & 0 deletions rtl/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
## 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`.


### [`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).


### [`templates`](https://github.com/stnolting/neorv32/tree/master/rtl/templates)

Alternative top entities / wrappers for the NEORV32 Processor.
53 changes: 53 additions & 0 deletions rtl/test_setups/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 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/).

:information_source: 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 [indidrect 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
stnolting marked this conversation as resolved.
Show resolved Hide resolved
[_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).


### [`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 [_Installing an Executable Directly Into Memory_](https://stnolting.github.io/neorv32/ug/#_installing_an_executable_directly_into_memory).
Loading