neorv32/docs/userguide/general_hw_setup.adoc

166 lines
8.4 KiB
Plaintext

<<<
:sectnums:
== General Hardware Setup
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 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 three minimalistic pre-configured test setups in
https://github.com/stnolting/neorv32/blob/main/rtl/test_setups[`rtl/test_setups`].
These test setups only implement very basic processor and CPU features.
The main difference between the 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.
* **`rtl/test_setups/neorv32_testsetup_on_chip_debugger.vhd`**: besides the UARt bootloader, this setups uses
on-chip debugger to upload and inspect new software executables. Use this setup if your board _does_ provide a JTAG
interface (the UART is optional).
.NEORV32 "hello world" test setup (`rtl/test_setups/neorv32_testsetup_bootloader.vhd`)
image::neorv32_test_setup.png[align=center]
.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.
.Internal Memories
[IMPORTANT]
For a _general_ first setup (technology-independent) use the `*.default.vhd` memory architectures for the internal memories
(IMEM and DMEM). These are located in `rtl/core/mem` so make sure to add the files to your project, too. +
+
If synthesis cannot efficiently map those default memory descriptions to the available memory resources, you can later replace the
default memory architectures by optimized platform-specific memory architectures. **Example:** The `neorv32-setups/radiant/UPduino_v3`
example setup uses optimized memory primitives. Hence, it does not include the default memory architectures from
`rtl/core/mem` as these are replaced by device-specific implementations. However, it still has to include the entity
definitions from `rtl/core`.
[start=3]
. 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.
.Compile order
[NOTE]
Some tools (like Lattice Radiant) might require a _manual compile order_ of the VHDL source files to identify the dependencies.
The package file `neorv32_package.vhd` should be analyzed first followed by the memory image files (`neorv32_application_imagevhd`
and `neorv32_bootloader_image.vhd`) and the entity-only files (`neorv32_*mem.entity.vhd`).
[start=4]
. 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]
. Add the pre-defined test setup of choice to the project, too, and select it as _top entity_.
. 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:
.Test setup entity - configuration generics
[source,vhdl]
----
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=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
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)
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=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 of the
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_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 -- UART0 receive data
);
----
.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 LED (see "Signal Polarity" note above).
. If your are using a UART-based test setup connect the UART communication signals `uart0_txd_o` and `uart0_rxd_i`
to the host interface (e.g. USB-UART converter).
. If your are using the on-chip debugger setup connect the processor's JTAG signal `jtag_*` to a suitable JTAG adapter.
. 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 LED(s) connected to `gpio_o` should be flashing now.
.Going Further
[TIP]
Now that the hardware is ready, you can advance to one of these chapters to learn how to get a software executable
into your processor setup (setup the GCC toolchain before; next section <<_general_software_framework_setup>>): +
+
`neorv32_testsetup_approm.vhd`: <<_installing_an_executable_directly_into_memory>>
+
`neorv32_testsetup_bootloader.vhd`: <<_uploading_and_starting_of_a_binary_executable_image_via_uart>>
+
`neorv32_testsetup_on_chip_debugger.vhd`: <<_debugging_using_the_on_chip_debugger>>