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 all 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
183 changes: 107 additions & 76 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,137 @@ 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-configured test setups in
https://github.com/stnolting/neorv32/blob/master/rtl/test_setups[`rtl/test_setups`].
Both test setups only implement very basic processor and CPU features.
The main difference between the two setups 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 _does_ provide a UART interface.

.NEORV32 "hello world" test setup (`rtl/test_setups/neorv32_testsetup_bootloader.vhd`)
image::neorv32_test_setup.png[align=center]

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.
.External Clock Source
[NOTE]
These test setups are intended to be directly used as **design top entity**. Of course you can also instantiate them
into another design unit. If your FPGA board only provides _very fast_ external clock sources (like on the FOMU board)
you might need to add clock management components (PLLs, DCMs, MMCMs, ...) to the test setup or to the according top entity
if you instantiate one of the test setups.

[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]

[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:
. 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:

.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_test_setup.vhd`
.Entity signals of `neorv32_testsetup_approm.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
);
----

.Entity signals of `neorv32_testsetup_bootloader.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
-- 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]
.Signal Polarity
[NOTE]
If your FPGA board has inverse polarity for certain input/output you can add `not` gates. Example: The reset signal
`rstn_i` is low-active by default; the LEDs connected to `gpio_o` high-active by default.
You can do this in your board top if you instantiate the test setup,
or _inside_ the test setup if this is your top entity (low-active LEDs example: `gpio_o <= NOT con_gpio_o(7 downto 0);`).

[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`.
. If possible, connected _at least_ bit `0` of the GPIO output port `gpio_o` to a LED (see "Signal Polarity" note above).
. 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.
6 changes: 0 additions & 6 deletions rtl/templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ This setup provides the minimal I/O, for testing the smallest possible design on

This processor setup provides 64kB of data and instruction memory, an RTOS-capable CPU (privileged architecture) and a set of standard peripherals like UART, TWI and SPI.

#### [`neorv32_ProcessorTop_Test.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/templates/processor/neorv32_ProcessorTop_Test.vhd)

This entity is intended as "FPGA hello world" example for playing with the NEORV32. It uses only some of the
provided peripherals and provides a very simple and basic interface - only the clock, reset, UART and a subset
of the GPIO output port are propagated to the outer world.

#### [`neorv32_ProcessorTop_stdlogic.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/templates/processor/neorv32_ProcessorTop_stdlogic.vhd)

Same entity (generics and interface ports) as the default NEORV32 Processor top entity (`rtl/core/neorv32_top.vhd`),
Expand Down
Loading