1 |
69 |
zero_gravi |
<<<
|
2 |
|
|
:sectnums:
|
3 |
|
|
== General Hardware Setup
|
4 |
|
|
|
5 |
|
|
This guide shows the basics of setting up a NEORV32 project for FPGA implementation (or simulation only)
|
6 |
|
|
_from scratch_. It uses a _simplified_ test "SoC" setup of the processor to keeps things simple at the beginning.
|
7 |
|
|
This simple setup is intended for evaluation or as "hello world" project to check out the NEORV32
|
8 |
|
|
on _your_ FPGA board.
|
9 |
|
|
|
10 |
|
|
[TIP]
|
11 |
|
|
If you want to use a more sophisticated pre-defined setup to start with, check out the
|
12 |
|
|
`setups` folder, which provides example setups for various FPGA, boards and toolchains.
|
13 |
|
|
|
14 |
|
|
The NEORV32 project features two minimalistic pre-configured test setups in
|
15 |
72 |
zero_gravi |
https://github.com/stnolting/neorv32/blob/main/rtl/test_setups[`rtl/test_setups`].
|
16 |
69 |
zero_gravi |
Both test setups only implement very basic processor and CPU features.
|
17 |
|
|
The main difference between the two setups is the processor boot concept - so how to get a software executable
|
18 |
|
|
_into_ the processor:
|
19 |
|
|
|
20 |
|
|
* **`rtl/test_setups/neorv32_testsetup_approm.vhd`**: this setup does not require a connection via UART. The
|
21 |
|
|
software executable is "installed" into the bitstream to initialize a read-only memory. Use this setup
|
22 |
|
|
if your FPGA board does _not_ provide a UART interface.
|
23 |
|
|
* **`rtl/test_setups/neorv32_testsetup_bootloader.vhd`**: this setups uses the UART and the default NEORV32
|
24 |
|
|
bootloader to upload new software executables. Use this setup if your board _does_ provide a UART interface.
|
25 |
|
|
|
26 |
|
|
.NEORV32 "hello world" test setup (`rtl/test_setups/neorv32_testsetup_bootloader.vhd`)
|
27 |
|
|
image::neorv32_test_setup.png[align=center]
|
28 |
|
|
|
29 |
|
|
.External Clock Source
|
30 |
|
|
[NOTE]
|
31 |
|
|
These test setups are intended to be directly used as **design top entity**. Of course you can also instantiate them
|
32 |
|
|
into another design unit. If your FPGA board only provides _very fast_ external clock sources (like on the FOMU board)
|
33 |
|
|
you might need to add clock management components (PLLs, DCMs, MMCMs, ...) to the test setup or to the according top entity
|
34 |
|
|
if you instantiate one of the test setups.
|
35 |
|
|
|
36 |
|
|
[start=1]
|
37 |
|
|
. Create a new project with your FPGA EDA tool of choice.
|
38 |
|
|
. Add all VHDL files from the project's `rtl/core` folder to your project.
|
39 |
|
|
|
40 |
|
|
.Internal Memories
|
41 |
|
|
[IMPORTANT]
|
42 |
|
|
For a _general_ first setup (technology-independent) use the `*.default.vhd` memory architectures for the internal memories
|
43 |
|
|
(IMEM and DMEM). These are located in `rtl/core/mem` so make sure to add the files to your project, too. +
|
44 |
|
|
+
|
45 |
|
|
If synthesis cannot efficiently map those default memory descriptions to the available memory resources, you can later replace the
|
46 |
71 |
zero_gravi |
default memory architectures by optimized platform-specific memory architectures. **Example:** The `neorv32-setups/radiant/UPduino_v3`
|
47 |
69 |
zero_gravi |
example setup uses optimized memory primitives. Hence, it does not include the default memory architectures from
|
48 |
|
|
`rtl/core/mem` as these are replaced by device-specific implementations. However, it still has to include the entity
|
49 |
|
|
definitions from `rtl/core`.
|
50 |
|
|
|
51 |
|
|
[start=3]
|
52 |
|
|
. Make sure to add all the rtl files to a new library called `neorv32`. If your FPGA tools does not
|
53 |
|
|
provide a field to enter the library name, check out the "properties" menu of the added rtl files.
|
54 |
|
|
|
55 |
|
|
.Compile order
|
56 |
|
|
[NOTE]
|
57 |
|
|
Some tools (like Lattice Radiant) might require a _manual compile order_ of the VHDL source files to identify the dependencies.
|
58 |
|
|
The package file `neorv32_package.vhd` should be analyzed first followed by the memory image files (`neorv32_application_imagevhd`
|
59 |
|
|
and `neorv32_bootloader_image.vhd`) and the entity-only files (`neorv32_*mem.entity.vhd`).
|
60 |
|
|
|
61 |
|
|
[start=4]
|
62 |
|
|
. The `rtl/core/neorv32_top.vhd` VHDL file is the top entity of the NEORV32 processor, which can be
|
63 |
|
|
instantiated into the "real" project. However, in this tutorial we will use one of the pre-defined
|
64 |
|
|
test setups from `rtl/test_setups` (see above).
|
65 |
|
|
|
66 |
|
|
[IMPORTANT]
|
67 |
|
|
Make sure to include the `neorv32` package into your design when instantiating the processor: add
|
68 |
|
|
`library neorv32;` and `use neorv32.neorv32_package.all;` to your design unit.
|
69 |
|
|
|
70 |
|
|
[start=5]
|
71 |
|
|
. Add the pre-defined test setup of choice to the project, too, and select it as _top entity_.
|
72 |
|
|
. The entity of both test setups
|
73 |
|
|
provide a minimal set of configuration generics, that might have to be adapted to match your FPGA and board:
|
74 |
|
|
|
75 |
|
|
.Test setup entity - configuration generics
|
76 |
|
|
[source,vhdl]
|
77 |
|
|
----
|
78 |
|
|
generic (
|
79 |
|
|
-- adapt these for your setup --
|
80 |
|
|
CLOCK_FREQUENCY : natural := 100000000; <1>
|
81 |
|
|
MEM_INT_IMEM_SIZE : natural := 16*1024; <2>
|
82 |
|
|
MEM_INT_DMEM_SIZE : natural := 8*1024 <3>
|
83 |
|
|
);
|
84 |
|
|
----
|
85 |
|
|
<1> Clock frequency of `clk_i` signal in Hertz
|
86 |
|
|
<2> Default size of internal instruction memory: 16kB
|
87 |
|
|
<3> Default size of internal data memory: 8kB
|
88 |
|
|
|
89 |
|
|
[start=7]
|
90 |
|
|
. If you feel like it - or if your FPGA does not provide sufficient resources - you can modify the
|
91 |
|
|
_memory sizes_ (`MEM_INT_IMEM_SIZE` and `MEM_INT_DMEM_SIZE` - marked with notes "2" and "3"). But as mentioned
|
92 |
|
|
above, let's keep things simple at first and use the standard configuration for now.
|
93 |
|
|
. There is one generic that _has to be set according to your FPGA board_ setup: the actual clock frequency
|
94 |
|
|
of the top's clock input signal (`clk_i`). Use the `CLOCK_FREQUENCY` generic to specify your clock source's
|
95 |
|
|
frequency in Hertz (Hz).
|
96 |
|
|
|
97 |
|
|
[NOTE]
|
98 |
|
|
If you have changed the default memory configuration (`MEM_INT_IMEM_SIZE` and `MEM_INT_DMEM_SIZE` generics)
|
99 |
|
|
keep those new sizes in mind - these values are required for setting
|
100 |
|
|
up the software framework in the next section <<_general_software_framework_setup>>.
|
101 |
|
|
|
102 |
|
|
[start=9]
|
103 |
|
|
. Depending on your FPGA tool of choice, it is time to assign the signals of the test setup top entity to
|
104 |
|
|
the according pins of your FPGA board. All the signals can be found in the entity declaration of the
|
105 |
|
|
corresponding test setup:
|
106 |
|
|
|
107 |
|
|
.Entity signals of `neorv32_testsetup_approm.vhd`
|
108 |
|
|
[source,vhdl]
|
109 |
|
|
----
|
110 |
|
|
port (
|
111 |
|
|
-- Global control --
|
112 |
|
|
clk_i : in std_ulogic; -- global clock, rising edge
|
113 |
|
|
rstn_i : in std_ulogic; -- global reset, low-active, async
|
114 |
|
|
-- GPIO --
|
115 |
|
|
gpio_o : out std_ulogic_vector(7 downto 0) -- parallel output
|
116 |
|
|
);
|
117 |
|
|
----
|
118 |
|
|
|
119 |
|
|
.Entity signals of `neorv32_testsetup_bootloader.vhd`
|
120 |
|
|
[source,vhdl]
|
121 |
|
|
----
|
122 |
|
|
port (
|
123 |
|
|
-- Global control --
|
124 |
|
|
clk_i : in std_ulogic; -- global clock, rising edge
|
125 |
|
|
rstn_i : in std_ulogic; -- global reset, low-active, async
|
126 |
|
|
-- GPIO --
|
127 |
|
|
gpio_o : out std_ulogic_vector(7 downto 0); -- parallel output
|
128 |
|
|
-- UART0 --
|
129 |
|
|
uart0_txd_o : out std_ulogic; -- UART0 send data
|
130 |
|
|
uart0_rxd_i : in std_ulogic -- UART0 receive data
|
131 |
|
|
);
|
132 |
|
|
----
|
133 |
|
|
|
134 |
|
|
.Signal Polarity
|
135 |
|
|
[NOTE]
|
136 |
|
|
If your FPGA board has inverse polarity for certain input/output you can add `not` gates. Example: The reset signal
|
137 |
|
|
`rstn_i` is low-active by default; the LEDs connected to `gpio_o` high-active by default.
|
138 |
|
|
You can do this in your board top if you instantiate the test setup,
|
139 |
|
|
or _inside_ the test setup if this is your top entity (low-active LEDs example: `gpio_o <= NOT con_gpio_o(7 downto 0);`).
|
140 |
|
|
|
141 |
|
|
[start=10]
|
142 |
|
|
. Attach the clock input `clk_i` to your clock source and connect the reset line `rstn_i` to a button of
|
143 |
|
|
your FPGA board. Check whether it is low-active or high-active - the reset signal of the processor is
|
144 |
|
|
**low-active**, so maybe you need to invert the input signal.
|
145 |
|
|
. If possible, connected _at least_ bit `0` of the GPIO output port `gpio_o` to a LED (see "Signal Polarity" note above).
|
146 |
|
|
. Finally, if your are using the UART-based test setup (`neorv32_testsetup_bootloader.vhd`)
|
147 |
|
|
connect the UART communication signals `uart0_txd_o` and `uart0_rxd_i` to the host interface (e.g. USB-UART converter).
|
148 |
|
|
. Perform the project HDL compilation (synthesis, mapping, bitstream generation).
|
149 |
|
|
. Program the generated bitstream into your FPGA and press the button connected to the reset signal.
|
150 |
|
|
. Done! The LED at `gpio_o(0)` should be flashing now.
|
151 |
|
|
|
152 |
|
|
[TIP]
|
153 |
|
|
After the GCC toolchain for compiling RISC-V source code is ready (chapter <<_general_software_framework_setup>>),
|
154 |
|
|
you can advance to one of these chapters to learn how to get a software executable into your processor setup:
|
155 |
|
|
* If you are using the `neorv32_testsetup_approm.vhd` setup: See section <<_installing_an_executable_directly_into_memory>>.
|
156 |
|
|
* If you are using the `neorv32_testsetup_bootloader.vhd` setup: See section <<_uploading_and_starting_of_a_binary_executable_image_via_uart>>.
|