Line 27... |
Line 27... |
|
|
|
|
:sectnums:
|
:sectnums:
|
=== Building the Toolchain from Scratch
|
=== Building the Toolchain from Scratch
|
|
|
To build the toolchain by yourself you can follow the guide from the official https://github.com/riscv/riscv-gnu-toolchain GitHub page.
|
To build the toolchain by yourself you can follow the guide from the official https://github.com/riscv-collab/riscv-gnu-toolchain GitHub page.
|
You need to make sure the generated toolchain fits the architecture of the NEORV32 core. To get a toolchain that even supports minimal
|
You need to make sure the generated toolchain fits the architecture of the NEORV32 core. To get a toolchain that even supports minimal
|
ISA extension configurations, it is recommend to compile for `rv32i` only. Please note that this minimal ISA also provides further ISA
|
ISA extension configurations, it is recommend to compile for `rv32i` only. Please note that this minimal ISA also provides further ISA
|
extensions like `m` or `c`. Of course you can use a `multilib` approach to generate
|
extensions like `m` or `c`. Of course you can use a _multilib_ approach to generate toolchains for several target ISAs at once.
|
toolchains for several target ISAs.
|
|
|
|
.Configuring GCC build for `rv32i` (minimal ISA)
|
.Configuring GCC build for `rv32i` (minimal ISA)
|
[source,bash]
|
[source,bash]
|
----
|
----
|
riscv-gnu-toolchain$ ./configure --prefix=/opt/riscv --with-arch=rv32i –-with-abi=ilp32
|
riscv-gnu-toolchain$ ./configure --prefix=/opt/riscv --with-arch=rv32i --with-abi=ilp32
|
riscv-gnu-toolchain$ make
|
riscv-gnu-toolchain$ make
|
----
|
----
|
|
|
[IMPORTANT]
|
[IMPORTANT]
|
Keep in mind that – for instance – a toolchain build with `--with-arch=rv32imc` only provides library code compiled with
|
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
|
compressed (`C`) and `mul`/`div` instructions (`M`)! Hence, this code cannot be executed (without
|
emulation) on an architecture without these extensions!
|
emulation) on an architecture without these extensions!
|
|
|
|
|
:sectnums:
|
:sectnums:
|
Line 194... |
Line 193... |
<1> Clock frequency of `clk_i` signal in Hertz
|
<1> Clock frequency of `clk_i` signal in Hertz
|
<2> Default size of internal instruction memory: 16kB
|
<2> Default size of internal instruction memory: 16kB
|
<3> Default size of internal data memory: 8kB
|
<3> Default size of internal data memory: 8kB
|
|
|
[start=7]
|
[start=7]
|
. If you feel like it – or if your FPGA does not provide sufficient resources – you can modify the
|
. 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
|
_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.
|
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
|
. 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
|
of the top's clock input signal (`clk_i`). Use the `CLOCK_FREQUENCY` generic to specify your clock source's
|
frequency in Hertz (Hz).
|
frequency in Hertz (Hz).
|
|
|
[NOTE]
|
[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
|
keep those new sizes in mind - these values are required for setting
|
up the software framework in the next section <<_general_software_framework_setup>>.
|
up the software framework in the next section <<_general_software_framework_setup>>.
|
|
|
[start=9]
|
[start=9]
|
. Depending on your FPGA tool of choice, it is time to assign the signals of the test setup top entity to
|
. 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
|
the according pins of your FPGA board. All the signals can be found in the entity declaration of the
|
Line 247... |
Line 246... |
You can do this in your board top if you instantiate the test setup,
|
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);`).
|
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]
|
[start=10]
|
. Attach the clock input `clk_i` to your clock source and connect the reset line `rstn_i` to a button of
|
. 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
|
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.
|
**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 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`)
|
. 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).
|
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).
|
. Perform the project HDL compilation (synthesis, mapping, bitstream generation).
|
Line 286... |
Line 285... |
.Cut-out of the linker script `neorv32.ld`: `ram` memory section configuration
|
.Cut-out of the linker script `neorv32.ld`: `ram` memory section configuration
|
[source,c]
|
[source,c]
|
----
|
----
|
MEMORY
|
MEMORY
|
{
|
{
|
ram (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 8*1024 # <1>
|
ram (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 8*1024 <1>
|
...
|
...
|
----
|
----
|
<1> Size of the data memory address space (right-most value) (internal/external DMEM); here 8kB
|
<1> Size of the data memory address space (right-most value) (internal/external DMEM); here 8kB
|
|
|
[start=2]
|
[start=2]
|
Line 614... |
Line 613... |
the `MABI` variable according to your CPU hardware configuration.
|
the `MABI` variable according to your CPU hardware configuration.
|
|
|
[source,makefile]
|
[source,makefile]
|
----
|
----
|
# CPU architecture and ABI
|
# CPU architecture and ABI
|
MARCH = -march=rv32i # <1>
|
MARCH ?= rv32i <1>
|
MABI = -mabi=ilp32 # <2>
|
MABI ?= ilp32 <2>
|
----
|
----
|
<1> MARCH = Machine architecture ("ISA string")
|
<1> MARCH = Machine architecture ("ISA string")
|
<2> MABI = Machine binary interface
|
<2> MABI = Machine binary interface
|
|
|
For example, if you enable the RISC-V `C` extension (16-bit compressed instructions) via the `CPU_EXTENSION_RISCV_C`
|
For example, if you enable the RISC-V `C` extension (16-bit compressed instructions) via the `CPU_EXTENSION_RISCV_C`
|
Line 640... |
Line 639... |
|
|
You can also override the default `MARCH` and `MABI` configurations from the makefile when invoking the makefile:
|
You can also override the default `MARCH` and `MABI` configurations from the makefile when invoking the makefile:
|
|
|
[source,bash]
|
[source,bash]
|
----
|
----
|
$ make MARCH=-march=rv32ic clean_all all
|
$ make MARCH=rv32ic clean_all all
|
----
|
----
|
|
|
[NOTE]
|
[NOTE]
|
The RISC-V ISA string for `MARCH` follows a certain _canonical_ structure:
|
The RISC-V ISA string for `MARCH` follows a certain _canonical_ structure:
|
`rev32[i/e][m][a][f][d][g][q][c][b][v][n]...` For example `rv32imac` is valid while `rv32icma` is not.
|
`rev32[i/e][m][a][f][d][g][q][c][b][v][n]...` For example `rv32imac` is valid while `rv32icma` is not.
|
Line 1035... |
Line 1034... |
. For all FPGA-external signals (like UART signals) make all the connections you need "external"
|
. For all FPGA-external signals (like UART signals) make all the connections you need "external"
|
(right-click on the signal/pin -> "Make External").
|
(right-click on the signal/pin -> "Make External").
|
. Save everything, let VIVADO create a HDL-Wrapper for the block-design and choose this as your _Top Level Design_.
|
. Save everything, let VIVADO create a HDL-Wrapper for the block-design and choose this as your _Top Level Design_.
|
. Define your constraints and generate your bitstream.
|
. Define your constraints and generate your bitstream.
|
|
|
|
.TWI Tri-State Drivers
|
|
[IMPORTANT]
|
|
Set the synthesis option "global" when generating the block design to maintain the internal TWI tri-state drivers.
|
|
|
[NOTE]
|
[NOTE]
|
Guide provided by GitHub user https://github.com/AWenzel83[`AWenzel83`] from
|
Guide provided by GitHub user https://github.com/AWenzel83[`AWenzel83`] (see
|
https://github.com/stnolting/neorv32/discussions/52#discussioncomment-819013
|
https://github.com/stnolting/neorv32/discussions/52#discussioncomment-819013). ❤️
|
|
|
|
|
|
|
|
|
// ####################################################################################################################
|
// ####################################################################################################################
|
Line 1179... |
Line 1182... |
:sectnums:
|
:sectnums:
|
==== Hello World!
|
==== Hello World!
|
|
|
To do a quick test of the NEORV32 make sure to have https://github.com/ghdl/ghdl[GHDL] and a
|
To do a quick test of the NEORV32 make sure to have https://github.com/ghdl/ghdl[GHDL] and a
|
[RISC-V gcc toolchain](https://github.com/stnolting/riscv-gcc-prebuilt) installed.
|
[RISC-V gcc toolchain](https://github.com/stnolting/riscv-gcc-prebuilt) installed.
|
Navigate to the project's `sw/example/hello_world` folder and run `make USER_FLAGS+=-DUART0_SIM_MODE MARCH=-march=rv32imac clean_all sim`:
|
Navigate to the project's `sw/example/hello_world` folder and run `make USER_FLAGS+=-DUART0_SIM_MODE MARCH=rv32imac clean_all sim`:
|
|
|
[TIP]
|
[TIP]
|
The simulator will output some _sanity check_ notes (and warnings or even errors if something is ill-configured)
|
The simulator will output some _sanity check_ notes (and warnings or even errors if something is ill-configured)
|
right at the beginning of the simulation to give a brief overview of the actual NEORV32 SoC and CPU configurations.
|
right at the beginning of the simulation to give a brief overview of the actual NEORV32 SoC and CPU configurations.
|
|
|
[source, bash]
|
[source, bash]
|
----
|
----
|
stnolting@Einstein:/mnt/n/Projects/neorv32/sw/example/hello_world$ make USER_FLAGS+=-DUART0_SIM_MODE MARCH=-march=rv32imac clean_all sim
|
stnolting@Einstein:/mnt/n/Projects/neorv32/sw/example/hello_world$ make USER_FLAGS+=-DUART0_SIM_MODE MARCH=rv32imac clean_all sim
|
../../../sw/lib/source/neorv32_uart.c: In function 'neorv32_uart0_setup':
|
../../../sw/lib/source/neorv32_uart.c: In function 'neorv32_uart0_setup':
|
../../../sw/lib/source/neorv32_uart.c:301:4: warning: #warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only! [-Wcpp]
|
../../../sw/lib/source/neorv32_uart.c:301:4: warning: #warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only! [-Wcpp]
|
301 | #warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only! <1>
|
301 | #warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only! <1>
|
| ^~~~~~~
|
| ^~~~~~~
|
Memory utilization:
|
Memory utilization:
|
Line 1308... |
Line 1311... |
|
|
|
|
|
|
// ####################################################################################################################
|
// ####################################################################################################################
|
:sectnums:
|
:sectnums:
|
|
== Zephyr RTOS Support 🪁
|
|
|
|
The NEORV32 processor is supported by upstream Zephyr RTOS: https://docs.zephyrproject.org/latest/boards/riscv/neorv32/doc/index.html
|
|
|
|
[IMPORTANT]
|
|
The absolute path to the NEORV32 executable image generator binary (`.../neorv32/sw/image_gen`) has to be added to the `PATH` variable
|
|
so the Zephyr build system can generate executables and memory-initialization images.
|
|
|
|
[NOTE]
|
|
Zephyr OS port provided by GitHub user https://github.com/henrikbrixandersen[henrikbrixandersen]
|
|
(see https://github.com/stnolting/neorv32/discussions/172). ❤️
|
|
|
|
|
|
|
|
|
|
// ####################################################################################################################
|
|
:sectnums:
|
== FreeRTOS Support
|
== FreeRTOS Support
|
|
|
A NEORV32-specific port and a simple demo for FreeRTOS (https://github.com/FreeRTOS/FreeRTOS) are
|
A NEORV32-specific port and a simple demo for FreeRTOS (https://github.com/FreeRTOS/FreeRTOS) are
|
available in the `sw/example/demo_freeRTOS` folder. See the according documentation (`sw/example/demo_freeRTOS/README.md`)
|
available in the `sw/example/demo_freeRTOS` folder. See the according documentation (`sw/example/demo_freeRTOS/README.md`)
|
for more information.
|
for more information.
|
Line 1434... |
Line 1454... |
Navigate to `sw/example/blink_led` and compile the application:
|
Navigate to `sw/example/blink_led` and compile the application:
|
|
|
.Compile the test application
|
.Compile the test application
|
[source, bash]
|
[source, bash]
|
--------------------------
|
--------------------------
|
.../neorv32/sw/example/blink_led$ make MARCH=-march=rv32i USER_FLAGS+=-g clean_all all
|
.../neorv32/sw/example/blink_led$ make MARCH=rv32i USER_FLAGS+=-g clean_all all
|
--------------------------
|
--------------------------
|
|
|
.Adding debug symbols to the executable
|
.Adding debug symbols to the executable
|
[NOTE]
|
[NOTE]
|
`USER_FLAGS+=-g` passes the `-g` flag to the compiler so it adds debug information/symbols
|
`USER_FLAGS+=-g` passes the `-g` flag to the compiler so it adds debug information/symbols
|