URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 51 to Rev 52
- ↔ Reverse comparison
Rev 51 → Rev 52
/neorv32/trunk/riscv-compliance/README.md
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v1.0/riscv-target/neorv32/compliance_io.h
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v1.0/riscv-target/neorv32/README.md
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32i/Makefile.include
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32imc/Makefile.include
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32Zicsr/Makefile.include
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32Zifencei/Makefile.include
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v1.0/riscv-target/neorv32/device/.ld_script/link.ld
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32im/Makefile.include
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v1.0/riscv-target/neorv32/compliance_test.h
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v2.0/riscv-target/neorv32/README.md
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v2.0/riscv-target/neorv32/link.imem_rom.ld
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v2.0/riscv-target/neorv32/device/rv32i_m/C/Makefile.include
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v2.0/riscv-target/neorv32/device/rv32i_m/I/Makefile.include
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v2.0/riscv-target/neorv32/device/rv32i_m/M/Makefile.include
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v2.0/riscv-target/neorv32/link.imem_ram.ld
File deleted
/neorv32/trunk/riscv-compliance/port-neorv32/framework_v2.0/riscv-target/neorv32/model_test.h
File deleted
/neorv32/trunk/riscv-compliance/work/.gitignore
File deleted
\ No newline at end of file
/neorv32/trunk/.ci/install.sh
4,8 → 4,8
set -e |
|
# Toolchain to be used |
RELEASE=rv32i-1.0.0 |
TOOLCHAIN=riscv32-unknown-elf.gcc-10.1.0.rv32i.ilp32.newlib |
RELEASE=rv32i-2.0.0 |
TOOLCHAIN=riscv32-unknown-elf.gcc-10.2.0.rv32i.ilp32.newlib |
|
# Download toolchain |
echo "Downloading prebuilt RISC-V GCC toolchain ($RELEASE : $TOOLCHAIN)..." |
/neorv32/trunk/docs/figures/neorv32_processor.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/neorv32/trunk/docs/NEORV32.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target/neorv32/device/.ld_script/link.ld
0,0 → 1,28
OUTPUT_ARCH( "riscv" ) |
ENTRY(_start) |
|
SECTIONS |
{ |
|
. = 0x00000000; |
.text : { |
*(.text.trap) |
*(.text.init) |
|
. = ALIGN(0x1000); |
*(.tohost) |
|
. = ALIGN(0x1000); |
*(.text) |
_etext = .; |
|
*(.data) |
*(.data.string) |
_edata = .; |
|
*(.bss) |
_end = .; |
|
} |
|
} |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32Zicsr/Makefile.include
0,0 → 1,39
ifndef NEORV32_HOME |
$(error NEORV32_HOME is undefined) |
endif |
|
LDSCRIPT = $(ROOTDIR)/riscv-target/neorv32/device/.ld_script/link.ld |
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\ CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_HOME)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led install; \ |
sh $(NEORV32_HOME)/sim/ghdl/ghdl_sim.sh --stop-time=100us >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32i |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) \ |
-I$(ROOTDIR)/riscv-test-env/ \ |
-I$(ROOTDIR)/riscv-test-env/p/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(LDSCRIPT) $$< \ |
-o $$@; |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32Zifencei/Makefile.include
0,0 → 1,40
ifndef NEORV32_HOME |
$(error NEORV32_HOME is undefined) |
endif |
|
LDSCRIPT = $(ROOTDIR)/riscv-target/neorv32/device/.ld_script/link.ld |
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\ CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zifencei/c\ CPU_EXTENSION_RISCV_Zifencei => true, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_HOME)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led install; \ |
sh $(NEORV32_HOME)/sim/ghdl/ghdl_sim.sh --stop-time=100us >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32i |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) \ |
-I$(ROOTDIR)/riscv-test-env/ \ |
-I$(ROOTDIR)/riscv-test-env/p/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(LDSCRIPT) $$< \ |
-o $$@; |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32i/Makefile.include
0,0 → 1,40
ifndef NEORV32_HOME |
$(error NEORV32_HOME is undefined) |
endif |
|
LDSCRIPT = $(ROOTDIR)/riscv-target/neorv32/device/.ld_script/link.ld |
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
sed -i '/CPU_EXTENSION_RISCV_C/c\ CPU_EXTENSION_RISCV_C => false, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\ CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_HOME)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led install; \ |
sh $(NEORV32_HOME)/sim/ghdl/ghdl_sim.sh --stop-time=100us >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32i |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) \ |
-I$(ROOTDIR)/riscv-test-env/ \ |
-I$(ROOTDIR)/riscv-test-env/p/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(LDSCRIPT) $$< \ |
-o $$@; |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32im/Makefile.include
0,0 → 1,40
ifndef NEORV32_HOME |
$(error NEORV32_HOME is undefined) |
endif |
|
LDSCRIPT = $(ROOTDIR)/riscv-target/neorv32/device/.ld_script/link.ld |
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
sed -i '/CPU_EXTENSION_RISCV_M/c\ CPU_EXTENSION_RISCV_M => true, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\ CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_HOME)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led install; \ |
sh $(NEORV32_HOME)/sim/ghdl/ghdl_sim.sh --stop-time=100us >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32im |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) \ |
-I$(ROOTDIR)/riscv-test-env/ \ |
-I$(ROOTDIR)/riscv-test-env/p/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(LDSCRIPT) $$< \ |
-o $$@; |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target/neorv32/device/rv32imc/Makefile.include
0,0 → 1,41
ifndef NEORV32_HOME |
$(error NEORV32_HOME is undefined) |
endif |
|
LDSCRIPT = $(ROOTDIR)/riscv-target/neorv32/device/.ld_script/link.ld |
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
sed -i '/CPU_EXTENSION_RISCV_C/c\ CPU_EXTENSION_RISCV_C => true, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_M/c\ CPU_EXTENSION_RISCV_M => true, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\ CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-COMPL. TEST SCRIPT' $(NEORV32_HOME)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_HOME)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_HOME)/sw/example/blink_led install; \ |
sh $(NEORV32_HOME)/sim/ghdl/ghdl_sim.sh --stop-time=100us >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32imc |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) \ |
-I$(ROOTDIR)/riscv-test-env/ \ |
-I$(ROOTDIR)/riscv-test-env/p/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(LDSCRIPT) $$< \ |
-o $$@; |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target/neorv32/README.md
0,0 → 1,18
# Simulation |
|
The NEORV32 Processor is simulated using the its default testbench. |
|
Each architecture-specific makefile in the `device` folder uses an _uncool hack_: `sed` is used to |
enable/disable the required `CPU_EXTENSION_RISCV_xxx` VHDL configuration generics in the testbench (`neorv32/sim/neorv32_tb.vhd`). |
|
For instance, the `rv32i` tests requires the `C`-extensions to be disabled - which is enabled by default in the testbench. |
|
GHDL is used for simulating the processor. |
|
The results are dumped via the SIM_MODE feature of the UART. The according code can be found in the `RV_COMPLIANCE_HALT` |
macro in `compliance_test.h`. |
|
The `RVTEST_IO_INIT` macro in `compliance_io.h` is used to configure |
the UART for SIM_MODE. |
|
The final data (plain 8-hex char data) is dumped to the `neorv32.uart.sim_mode.data.out` file. |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target/neorv32/compliance_io.h
0,0 → 1,47
// RISC-V Compliance IO Test Header File |
|
/* |
* Copyright (c) 2005-2018 Imperas Software Ltd., www.imperas.com |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
* either express or implied. |
* |
* See the License for the specific language governing permissions and |
* limitations under the License. |
* |
*/ |
|
// Modified by Stephan Nolting for the NEORV32 Processor |
|
#ifndef _COMPLIANCE_IO_H |
#define _COMPLIANCE_IO_H |
|
//----------------------------------------------------------------------- |
// RV IO Macros |
//----------------------------------------------------------------------- |
|
// enable UART (ctrl(28)) and enable UART_SIM_MODE (ctrl(12)) |
#define RVTEST_IO_INIT \ |
uart_init: \ |
li a0, 0xFFFFFFA0; \ |
sw zero, 0(a0); \ |
li a1, 1 << 28; \ |
li a2, 1 << 12; \ |
or a1, a1, a2; \ |
sw a1, 0(a0); \ |
|
#define RVTEST_IO_WRITE_STR(_R, _STR) |
#define RVTEST_IO_CHECK() |
#define RVTEST_IO_ASSERT_GPR_EQ(_G, _R, _I) |
#define RVTEST_IO_ASSERT_SFPR_EQ(_F, _R, _I) |
#define RVTEST_IO_ASSERT_DFPR_EQ(_D, _R, _I) |
|
#endif // _COMPLIANCE_IO_H |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target/neorv32/compliance_test.h
0,0 → 1,47
// RISC-V Compliance Test Header File |
// Copyright (c) 2017, Codasip Ltd. All Rights Reserved. |
// See LICENSE for license details. |
// |
// Description: Common header file for RV32I tests |
|
// Modified by Stephan Nolting for the NEORV32 Processor |
|
#ifndef _COMPLIANCE_TEST_H |
#define _COMPLIANCE_TEST_H |
|
#include "riscv_test.h" |
|
//----------------------------------------------------------------------- |
// RV Compliance Macros |
//----------------------------------------------------------------------- |
|
// this will dump the results via the UART_SIM_MODE data file output |
#define RV_COMPLIANCE_HALT \ |
la a0, begin_signature; \ |
la a1, end_signature; \ |
li a2, 0xFFFFFFA4; \ |
copy_loop: \ |
beq a0, a1, copy_loop_end; \ |
lw t0, 0(a0); \ |
sw t0, 0(a2); \ |
addi a0, a0, 4; \ |
j copy_loop; \ |
copy_loop_end: \ |
RVTEST_PASS \ |
|
#define RV_COMPLIANCE_RV32M \ |
RVTEST_RV32M \ |
|
#define RV_COMPLIANCE_CODE_BEGIN \ |
RVTEST_CODE_BEGIN \ |
|
#define RV_COMPLIANCE_CODE_END \ |
RVTEST_CODE_END \ |
|
#define RV_COMPLIANCE_DATA_BEGIN \ |
RVTEST_DATA_BEGIN \ |
|
#define RV_COMPLIANCE_DATA_END \ |
RVTEST_DATA_END \ |
|
#endif |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/device/rv32i_m/C/Makefile.include
0,0 → 1,52
ifndef NEORV32_LOCAL_COPY |
$(error NEORV32_LOCAL_COPY is undefined) |
endif |
|
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
echo "copying/using SIM-only IMEM (ROM!)"; \ |
rm -f $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
cp -f $(NEORV32_LOCAL_COPY)/sim/rtl_modules/neorv32_imem.vhd $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_A/c\CPU_EXTENSION_RISCV_A => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_C/c\CPU_EXTENSION_RISCV_C => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_E/c\CPU_EXTENSION_RISCV_E => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_M/c\CPU_EXTENSION_RISCV_M => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_U/c\CPU_EXTENSION_RISCV_U => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zifencei/c\CPU_EXTENSION_RISCV_Zifencei => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/constant ext_imem_c/c\constant ext_imem_c : boolean := false; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/signal ext_ram_a : ext_mem_a_ram_t/c\signal ext_ram_a : ext_mem_a_ram_t; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_USE/c\MEM_INT_IMEM_USE => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_SIZE/c\MEM_INT_IMEM_SIZE => 2*1024*1024, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_ROM/c\MEM_INT_IMEM_ROM => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_LOCAL_COPY)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led install; \ |
sed -i '/type application_init_image_t/c\type application_init_image_t is array (0 to ((2*1024*1024)/4)-1) of std_ulogic_vector(31 downto 0); -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_application_image.vhd; \ |
sh $(NEORV32_LOCAL_COPY)/sim/ghdl/ghdl_sim.sh --stop-time=$(SIM_TIME) >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart0.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32ic -mabi=ilp32 |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \ |
$$(RISCV_TARGET_FLAGS) \ |
-I$(ROOTDIR)/riscv-test-suite/env/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(TARGETDIR)/$(RISCV_TARGET)/link.imem_rom.ld \ |
$$(<) -o $$@ |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/device/rv32i_m/I/Makefile.include
0,0 → 1,52
ifndef NEORV32_LOCAL_COPY |
$(error NEORV32_LOCAL_COPY is undefined) |
endif |
|
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
echo "copying/using SIM-only IMEM (ROM!)"; \ |
rm -f $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
cp -f $(NEORV32_LOCAL_COPY)/sim/rtl_modules/neorv32_imem.vhd $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_A/c\CPU_EXTENSION_RISCV_A => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_C/c\CPU_EXTENSION_RISCV_C => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_E/c\CPU_EXTENSION_RISCV_E => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_M/c\CPU_EXTENSION_RISCV_M => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_U/c\CPU_EXTENSION_RISCV_U => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zifencei/c\CPU_EXTENSION_RISCV_Zifencei => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/constant ext_imem_c/c\constant ext_imem_c : boolean := false; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/signal ext_ram_a : ext_mem_a_ram_t/c\signal ext_ram_a : ext_mem_a_ram_t; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_USE/c\MEM_INT_IMEM_USE => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_SIZE/c\MEM_INT_IMEM_SIZE => 2*1024*1024, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_ROM/c\MEM_INT_IMEM_ROM => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_LOCAL_COPY)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led install; \ |
sed -i '/type application_init_image_t/c\type application_init_image_t is array (0 to ((2*1024*1024)/4)-1) of std_ulogic_vector(31 downto 0); -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_application_image.vhd; \ |
sh $(NEORV32_LOCAL_COPY)/sim/ghdl/ghdl_sim.sh --stop-time=$(SIM_TIME) >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart0.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32i -mabi=ilp32 |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \ |
$$(RISCV_TARGET_FLAGS) \ |
-I$(ROOTDIR)/riscv-test-suite/env/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(TARGETDIR)/$(RISCV_TARGET)/link.imem_rom.ld \ |
$$(<) -o $$@ |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/device/rv32i_m/M/Makefile.include
0,0 → 1,52
ifndef NEORV32_LOCAL_COPY |
$(error NEORV32_LOCAL_COPY is undefined) |
endif |
|
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
echo "copying/using SIM-only IMEM (ROM!)"; \ |
rm -f $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
cp -f $(NEORV32_LOCAL_COPY)/sim/rtl_modules/neorv32_imem.vhd $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_A/c\CPU_EXTENSION_RISCV_A => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_C/c\CPU_EXTENSION_RISCV_C => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_E/c\CPU_EXTENSION_RISCV_E => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_M/c\CPU_EXTENSION_RISCV_M => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_U/c\CPU_EXTENSION_RISCV_U => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zifencei/c\CPU_EXTENSION_RISCV_Zifencei => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/constant ext_imem_c/c\constant ext_imem_c : boolean := false; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/signal ext_ram_a : ext_mem_a_ram_t/c\signal ext_ram_a : ext_mem_a_ram_t; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_USE/c\MEM_INT_IMEM_USE => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_SIZE/c\MEM_INT_IMEM_SIZE => 2*1024*1024, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_ROM/c\MEM_INT_IMEM_ROM => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_LOCAL_COPY)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led install; \ |
sed -i '/type application_init_image_t/c\type application_init_image_t is array (0 to ((2*1024*1024)/4)-1) of std_ulogic_vector(31 downto 0); -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_application_image.vhd; \ |
sh $(NEORV32_LOCAL_COPY)/sim/ghdl/ghdl_sim.sh --stop-time=$(SIM_TIME) >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart0.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32im -mabi=ilp32 |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \ |
$$(RISCV_TARGET_FLAGS) \ |
-I$(ROOTDIR)/riscv-test-suite/env/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(TARGETDIR)/$(RISCV_TARGET)/link.imem_rom.ld \ |
$$(<) -o $$@ |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/device/rv32i_m/Zifencei/Makefile.include
0,0 → 1,51
ifndef NEORV32_LOCAL_COPY |
$(error NEORV32_LOCAL_COPY is undefined) |
endif |
|
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
echo "restoring/using original IMEM rtl file"; \ |
rm -f $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
cp -f $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.ORIGINAL $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_A/c\CPU_EXTENSION_RISCV_A => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_C/c\CPU_EXTENSION_RISCV_C => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_E/c\CPU_EXTENSION_RISCV_E => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_M/c\CPU_EXTENSION_RISCV_M => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_U/c\CPU_EXTENSION_RISCV_U => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zifencei/c\CPU_EXTENSION_RISCV_Zifencei => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/constant ext_imem_c/c\constant ext_imem_c : boolean := false; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/signal ext_ram_a : ext_mem_a_ram_t/c\signal ext_ram_a : ext_mem_a_ram_t; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_USE/c\MEM_INT_IMEM_USE => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_SIZE/c\MEM_INT_IMEM_SIZE => 32*1024, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_ROM/c\MEM_INT_IMEM_ROM => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_LOCAL_COPY)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led install; \ |
sh $(NEORV32_LOCAL_COPY)/sim/ghdl/ghdl_sim.sh --stop-time=$(SIM_TIME) >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart0.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32i -mabi=ilp32 |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \ |
$$(RISCV_TARGET_FLAGS) \ |
-I$(ROOTDIR)/riscv-test-suite/env/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(TARGETDIR)/$(RISCV_TARGET)/link.imem_ram.ld \ |
$$(<) -o $$@ |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/device/rv32i_m/privilege/Makefile.include
0,0 → 1,52
ifndef NEORV32_LOCAL_COPY |
$(error NEORV32_LOCAL_COPY is undefined) |
endif |
|
TARGET_SIM ?= ghdl |
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS) |
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),) |
$(error Target simulator executable '$(TARGET_SIM)` not found) |
endif |
|
RUN_TARGET=\ |
cd $(work_dir_isa); \ |
rm -f $(work_dir_isa)/*.out; \ |
echo "copying/using SIM-only IMEM (ROM!)"; \ |
rm -f $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
cp -f $(NEORV32_LOCAL_COPY)/sim/rtl_modules/neorv32_imem.vhd $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_imem.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_A/c\CPU_EXTENSION_RISCV_A => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_C/c\CPU_EXTENSION_RISCV_C => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_E/c\CPU_EXTENSION_RISCV_E => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_M/c\CPU_EXTENSION_RISCV_M => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_U/c\CPU_EXTENSION_RISCV_U => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zicsr/c\CPU_EXTENSION_RISCV_Zicsr => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/CPU_EXTENSION_RISCV_Zifencei/c\CPU_EXTENSION_RISCV_Zifencei => false, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/constant ext_imem_c/c\constant ext_imem_c : boolean := false; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/signal ext_ram_a : ext_mem_a_ram_t/c\signal ext_ram_a : ext_mem_a_ram_t; -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_USE/c\MEM_INT_IMEM_USE => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_SIZE/c\MEM_INT_IMEM_SIZE => 2*1024*1024, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
sed -i '/MEM_INT_IMEM_ROM/c\MEM_INT_IMEM_ROM => true, -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/sim/neorv32_tb.vhd; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.elf; \ |
cp -f $< $(NEORV32_LOCAL_COPY)/sw/example/blink_led/main.elf; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led main.bin; \ |
make -C $(NEORV32_LOCAL_COPY)/sw/example/blink_led install; \ |
sed -i '/type application_init_image_t/c\type application_init_image_t is array (0 to ((2*1024*1024)/4)-1) of std_ulogic_vector(31 downto 0); -- MOD. BY RISCV-ARCH-TEST TEST SCRIPT' $(NEORV32_LOCAL_COPY)/rtl/core/neorv32_application_image.vhd; \ |
sh $(NEORV32_LOCAL_COPY)/sim/ghdl/ghdl_sim.sh --stop-time=$(SIM_TIME) >> /dev/null; \ |
cp $(work_dir_isa)/neorv32.uart0.sim_mode.data.out $(*).signature.output; |
|
|
RISCV_PREFIX ?= riscv32-unknown-elf- |
RISCV_GCC ?= $(RISCV_PREFIX)gcc |
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump |
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy |
RISCV_READELF ?= $(RISCV_PREFIX)readelf |
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32i -mabi=ilp32 |
|
COMPILE_TARGET=\ |
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \ |
$$(RISCV_TARGET_FLAGS) \ |
-I$(ROOTDIR)/riscv-test-suite/env/ \ |
-I$(TARGETDIR)/$(RISCV_TARGET)/ \ |
-T$(TARGETDIR)/$(RISCV_TARGET)/link.imem_rom.ld \ |
$$(<) -o $$@ |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/README.md
0,0 → 1,29
# Running the RISC-V riscv-arch-test Test Suite in Simulation |
|
|
The following tasks are executed by the device makefiles: |
|
* replace the original processor's IMEM rtl file by a simulation-optimized IMEM (ROM!) |
* `sed` command is used to modify the default testbench (`neorv32/sim/neorv32_tb.vhd`): |
* enable/disable the required `CPU_EXTENSION_RISCV_xxx` VHDL configuration generics in the testbench (`neorv32/sim/neorv32_tb.vhd`) |
* configure the processor memory configuration (use internal IMEM, IMEM as ROM, IMEM size of 2MB) |
* compile test code and install application image to processor's `rtl/core` folder |
* compilation uses the `link.imem_rom.ld` linker script as default; code (the test code) is executed from IMEM (which is read-only); data including signature is stored to DMEM (RAM) |
* certain areas in the DMEM are initialized using port code in `model_test.h` (`RVTEST` = 0xbabecafe and `SIGNATURE` = 0xdeadbeef); can be disabled using `RISCV_TARGET_FLAGS=-DNEORV32_NO_DATA_INIT` |
* `sed` command is used to modify the default application image that is generated during compilation (`neorv32/rtl/core/neorv32_application_image.vhd`): |
* the array size of the application image is set to 2MB |
* the processor is simulated using the default testbench using GHDL |
* the results are dumped via the SIM_MODE feature of the UART |
* the according code can be found in the `RVMODEL_HALT` macro in `model_test.h` |
* data output (the "signature") is zero-padded to be always a multiple of 16 bytes |
|
|
**Notes** |
|
:warning: The `Zifencei` test requires the r/w/e capabilities of the original IMEM rtl file. |
Hence, the original file is restored for this test. Also, this test uses `link.imem_ram.ld` as linker script since the |
IMEM is used as RAM to allow self-modifying code. |
|
:information_source: The `RVMODEL_BOOT` macro in `model_test.h` provides a simple "dummy trap handler" that just advances to the next instruction. This trap handler is required |
for some `C` tests as the NEORV32 will raise an illegal instruction exception for **all** unimplemented instructions. The trap handler is overriden (by changing `mtval` CSR) if |
a test uses the defualt trap handler of the test framework. |
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/link.imem_ram.ld
0,0 → 1,22
OUTPUT_ARCH( "riscv" ) |
ENTRY(rvtest_entry_point) |
|
SECTIONS |
{ |
. = 0x00000000; |
.text : |
{ |
*(.text.init) |
. = ALIGN(0x1000); |
*(.text) |
. = ALIGN(0x1000); |
*(.tohost) |
*(.data) |
*(.data.string) |
*(.bss) |
. = ALIGN(0x1000); |
|
_end = .; |
} |
} |
|
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/link.imem_rom.ld
0,0 → 1,26
OUTPUT_ARCH( "riscv" ) |
ENTRY(rvtest_entry_point) |
|
SECTIONS |
{ |
. = 0x00000000; |
.text : |
{ |
*(.text.init) |
. = ALIGN(0x1000); |
*(.text) |
. = ALIGN(0x1000); |
_end = .; |
} |
|
. = 0x80000000; |
.data : |
{ |
. = ALIGN(0x1000); |
*(.tohost) |
*(.data) |
*(.data.string) |
*(.bss) |
} |
} |
|
/neorv32/trunk/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/model_test.h
0,0 → 1,210
// SPDX-License-Identifier: BSD-3-Clause |
|
// Modified by Stephan Nolting for the NEORV32 Processor |
|
#ifndef _COMPLIANCE_MODEL_H |
#define _COMPLIANCE_MODEL_H |
|
#define RVMODEL_DATA_SECTION \ |
.pushsection .tohost,"aw",@progbits; \ |
.align 8; .global tohost; tohost: .dword 0; \ |
.align 8; .global fromhost; fromhost: .dword 0; \ |
.popsection; \ |
.align 8; .global begin_regstate; begin_regstate: \ |
.word 128; \ |
.align 8; .global end_regstate; end_regstate: \ |
.word 4; |
|
//RV_COMPLIANCE_HALT |
// neorv32: this will dump the results via the UART0_SIM_MODE data file output |
// neorv32: due to the modifications on "end_signature" (not 4-aligned) we need to make sure we output a 4-aligned number of data here |
// neorv32: -> for zero-padding of the rest of the SIGNATURE section |
#define RVMODEL_HALT \ |
signature_dump: \ |
la a0, begin_signature; \ |
la a1, end_signature; \ |
li a2, 0xFFFFFFA4; \ |
signature_dump_loop: \ |
beq a0, a1, signature_dump_padding; \ |
lw t0, 0(a0); \ |
sw t0, 0(a2); \ |
addi a0, a0, 4; \ |
j signature_dump_loop; \ |
nop; \ |
nop; \ |
signature_dump_padding: \ |
andi a0, a1, 0x0000000C; \ |
beq a0, zero, signature_dump_end; \ |
li t0, 16; \ |
sub a0, t0, a0; \ |
signature_dump_padding_loop: \ |
beq a0, zero, signature_dump_end; \ |
sw zero, 0(a2); \ |
addi a0, a0, -4; \ |
j signature_dump_padding_loop; \ |
signature_dump_end: \ |
j signature_dump_end |
|
//TODO: declare the start of your signature region here. Nothing else to be used here. |
// The .align 4 ensures that the signature ends at a 16-byte boundary |
#define RVMODEL_DATA_BEGIN \ |
.align 4; .global begin_signature; begin_signature: |
|
//TODO: declare the end of the signature region here. Add other target specific contents here. |
//neorv32: DO NOT use align_4 here! end_signature is used to indicate the actual "number" of signature words |
#define RVMODEL_DATA_END \ |
.global end_signature; end_signature: \ |
RVMODEL_DATA_SECTION |
|
//RVMODEL_BOOT |
// neorv32: enable UART0 (ctrl(28)) and enable UART0_SIM_MODE (ctrl(12)) |
// neorv32: initialize the complete RVTEST_DATA section in data RAM (DMEM) with 0xBABECAFE |
// neorv32: initialize the complete SIGNATURE section (that is a multiple of four 32-bit entries) in data RAM (DMEM) with 0xDEADBEEF |
// neorv32: this code also provides a dummy trap handler that just moves on to the next instruction |
// neorv32: -> this trap handler can be overriden by the compliance-suite by modifying mtval |
// neorv32: -> the dummy trap handler is required to deal with the neorv32 X extension (-> all illegal/undefined instruction trigger an exception) |
#ifdef NEORV32_NO_DATA_INIT |
// ------------------------- WITHOUT DATA INIT ------------------------- |
#define RVMODEL_BOOT \ |
core_init: \ |
la x1, core_dummy_trap_handler; \ |
csrw mtvec, x1; \ |
j uart0_sim_mode_init; \ |
nop; \ |
nop; \ |
.balign 4; \ |
core_dummy_trap_handler: \ |
csrw mscratch, sp; \ |
la sp, end_signature; \ |
addi sp, sp, 32; \ |
sw x8, 0(sp); \ |
sw x9, 4(sp); \ |
csrr x8, mcause; \ |
blt x8, zero, core_dummy_trap_handler_irq; \ |
csrr x8, mepc; \ |
core_dummy_trap_handler_exc_c_check: \ |
lh x9, 0(x8); \ |
andi x9, x9, 3; \ |
addi x8, x8, +2; \ |
csrw mepc, x8; \ |
addi x8, zero, 3; \ |
bne x8, x9, core_dummy_trap_handler_irq; \ |
core_dummy_trap_handler_exc_uncrompressed: \ |
csrr x8, mepc; \ |
addi x8, x8, +2; \ |
csrw mepc, x8; \ |
core_dummy_trap_handler_irq: \ |
lw x9, 0(sp); \ |
lw x8, 4(sp); \ |
csrr sp, mscratch; \ |
mret; \ |
nop; \ |
nop; \ |
uart0_sim_mode_init: \ |
li a0, 0xFFFFFFA0; \ |
sw zero, 0(a0); \ |
li a1, 1 << 28; \ |
li a2, 1 << 12; \ |
or a1, a1, a2; \ |
sw a1, 0(a0); |
|
#else |
|
// ------------------------- WITH DATA INIT ------------------------- |
#define RVMODEL_BOOT \ |
core_init: \ |
la x1, core_dummy_trap_handler; \ |
csrw mtvec, x1; \ |
nop; \ |
nop; \ |
init_rvtest_data: \ |
la a0, rvtest_data_begin; \ |
la a1, rvtest_data_end; \ |
li a2, 0xBABECAFE; \ |
init_rvtest_data_loop: \ |
beq a0, a1, init_rvtest_data_loop_end; \ |
sw a2, 0(a0); \ |
addi a0, a0, 4; \ |
j init_rvtest_data_loop; \ |
init_rvtest_data_loop_end: \ |
nop; \ |
nop; \ |
init_signature: \ |
la a0, begin_signature; \ |
la a1, end_signature; \ |
li a2, 0xDEADBEEF; \ |
init_signature_loop: \ |
beq a0, a1, init_signature_loop_end; \ |
sw a2, 0(a0); \ |
addi a0, a0, 4; \ |
j init_signature_loop; \ |
init_signature_loop_end: \ |
j uart0_sim_mode_init; \ |
nop; \ |
nop; \ |
.balign 4; \ |
core_dummy_trap_handler: \ |
csrw mscratch, sp; \ |
la sp, end_signature; \ |
addi sp, sp, 32; \ |
sw x8, 0(sp); \ |
sw x9, 4(sp); \ |
csrr x8, mcause; \ |
blt x8, zero, core_dummy_trap_handler_irq; \ |
csrr x8, mepc; \ |
core_dummy_trap_handler_exc_c_check: \ |
lh x9, 0(x8); \ |
andi x9, x9, 3; \ |
addi x8, x8, +2; \ |
csrw mepc, x8; \ |
addi x8, zero, 3; \ |
bne x8, x9, core_dummy_trap_handler_irq; \ |
core_dummy_trap_handler_exc_uncrompressed: \ |
csrr x8, mepc; \ |
addi x8, x8, +2; \ |
csrw mepc, x8; \ |
core_dummy_trap_handler_irq: \ |
lw x9, 0(sp); \ |
lw x8, 4(sp); \ |
csrr sp, mscratch; \ |
mret; \ |
nop; \ |
nop; \ |
uart0_sim_mode_init: \ |
li a0, 0xFFFFFFA0; \ |
sw zero, 0(a0); \ |
li a1, 1 << 28; \ |
li a2, 1 << 12; \ |
or a1, a1, a2; \ |
sw a1, 0(a0); |
|
#endif |
|
|
//RVTEST_IO_INIT |
#define RVMODEL_IO_INIT |
//RVTEST_IO_WRITE_STR |
#define RVMODEL_IO_WRITE_STR(_R, _STR) |
//RVTEST_IO_CHECK |
#define RVMODEL_IO_CHECK() |
|
//RVTEST_IO_ASSERT_GPR_EQ |
#define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I) |
//RVTEST_IO_ASSERT_SFPR_EQ |
#define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I) |
//RVTEST_IO_ASSERT_DFPR_EQ |
#define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I) |
|
// TODO: specify the routine for setting machine software interrupt |
#define RVMODEL_SET_MSW_INT |
|
// TODO: specify the routine for clearing machine software interrupt |
#define RVMODEL_CLEAR_MSW_INT |
|
// TODO: specify the routine for clearing machine timer interrupt |
#define RVMODEL_CLEAR_MTIMER_INT |
|
// TODO: specify the routine for clearing machine external interrupt |
#define RVMODEL_CLEAR_MEXT_INT |
|
#endif // _COMPLIANCE_MODEL_H |
/neorv32/trunk/riscv-arch-test/work/.gitignore
0,0 → 1,2
neorv32 |
riscv-arch-test |
/neorv32/trunk/riscv-arch-test/README.md
0,0 → 1,50
# NEORV32 RISC-V Architecture Test Framework |
|
## Overview |
|
This sub-project folder tests the [NEORV32 Processor Core](https://github.com/stnolting/neorv32) |
using the [official RISC-V architecture test suite v2+](https://github.com/riscv/riscv-arch-test). The core's HDL sources are *simulated* using |
`GHDL` to provide a virtual execution platform for the test framework. |
|
The following tests are supported yet: |
|
* `rv32i_m/C` |
* `rv32i_m/I` |
* `rv32i_m/M` |
* `rv32i_m/privilege` |
* `rv32i_m/Zifencei` |
|
|
## How To Run |
|
**Requirements:** |
* `RISC-V GCC` toolchain (`riscv32-unknown-elf`) |
* `GHDL` for simulating the processor |
|
To **execute all the supported tests** open a terminal an run (:warning: simulating everything takes quite some time): |
|
$ sh run_riscv_arch_test.sh |
|
|
## Details |
|
The [`run_riscv_arch_test.sh`](https://github.com/stnolting/neorv32/blob/master/riscv-arch-test/run_riscv_arch_test.sh) |
bash script does the following: |
|
* Copy the `rtl`, `sim` and `sw` folders of the NEORV32 into `work/neorv32/` to keep the project's core files clean |
* Clone (if not already there) the [riscv-arch-test repository](https://github.com/riscv/riscv-arch-test) into `work/` |
* Install (copy) the custom `neorv32` test target from the `port-neorv32/framework_v2.0/riscv-target` folder to the riscv-arch-test suite's target folder |
* Replace the original DMEM VHDL source file of the processor (in `work/neorv32/rtl/core/neorv32_dmem.vhd`) by the simulation-optimized file (`neorv32/sim/rtl_modules/neorv32_dmem.vhd` to allow faster simulation) |
* Make a copy of the original IMEM VHDL source file of the processor (in `work/neorv32/rtl/core/neorv32_imem.vhd`) by the simulation-optimized file (`work/neorv32/rtl/core/neorv32_imem.ORIGINAL`); the original IMEM will be overriden by the device makefiles with a simulation-optimized one (`neorv32/sim/rtl_modules/neorv32_imem.vhd`); the original IMEM is required for certain tests that use self-modifying code |
* Run the actual riscv-arch-test tests |
|
More datails regarding the actual simulation process can be found in the [target's |
`README`](https://github.com/stnolting/neorv32/blob/master/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32/README.md). |
For more information regarding the NEORV32 Processor see the :page_facing_up: |
[NEORV32 data sheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf). |
|
:information_source: The port files for the *old framework (v1.0)* (riscv-compliance) can be found in |
[`port-neorv32/framework_v1.0`](https://github.com/stnolting/neorv32/tree/master/riscv-arch-test/port-neorv32/framework_v1.0/riscv-target). |
|
:information_source: If the simulation of a test does not generate any signature output at all or if the signature is truncated |
try increasing the simulation time by modiying the `SIM_TIME` variable when calling the test makefiles in `run_riscv_arch_test.sh`. |
/neorv32/trunk/riscv-arch-test/run_riscv_arch_test.sh
0,0 → 1,94
#!/bin/bash |
|
# Abort if any command returns != 0 |
set -e |
|
# Project home folder |
homedir="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" |
homedir=$homedir/.. |
|
# Check GCC toolchain installation |
echo "--------------------------------------------------------------------------" |
echo "> Checking RISC-V GCC toolchain..." |
echo "--------------------------------------------------------------------------" |
riscv32-unknown-elf-gcc -v |
|
# Check GHDL installation |
echo "--------------------------------------------------------------------------" |
echo "> Checking GHDL simulator..." |
echo "--------------------------------------------------------------------------" |
ghdl -v |
|
# Clone RISC-V Compliance Test Suite GitHub repository if it not exists already |
echo "--------------------------------------------------------------------------" |
echo "> Checking 'riscv-arch-test' GitHub repository..." |
echo "--------------------------------------------------------------------------" |
|
REPOSRC=https://github.com/riscv/riscv-arch-test.git |
LOCALREPO=$homedir/riscv-arch-test/work/riscv-arch-test |
LOCALREPO_VC_DIR=$LOCALREPO/.git |
|
if [ ! -d $LOCALREPO_VC_DIR ] |
then |
echo ">>> Cloning repository..." |
git clone $REPOSRC $LOCALREPO |
else |
echo ">>> Repository already exists. Checking for updates..." |
(cd $homedir/riscv-arch-test/work/riscv-arch-test ; git status -uno) |
fi |
|
# Copy NEORV32 files |
echo "--------------------------------------------------------------------------" |
echo "> Making local copy of NEORV32 'rtl', 'sim' & 'sw' folders..." |
echo "--------------------------------------------------------------------------" |
(cd $homedir/riscv-arch-test/work ; rm -rf neorv32 ; mkdir neorv32) |
cp -r $homedir/rtl/ $homedir/riscv-arch-test/work/neorv32/. |
cp -r $homedir/sim/ $homedir/riscv-arch-test/work/neorv32/. |
cp -r $homedir/sw/ $homedir/riscv-arch-test/work/neorv32/. |
|
# Copy neorv32 target folder into test suite |
echo "--------------------------------------------------------------------------" |
echo "> Copying neorv32 test-target into riscv-arch-test framework..." |
echo "--------------------------------------------------------------------------" |
cp -rf $homedir/riscv-arch-test/port-neorv32/framework_v2.0/riscv-target/neorv32 $homedir/riscv-arch-test/work/riscv-arch-test/riscv-target/. |
|
# Use simulation-optimized DMEM |
echo "" |
echo ">>> Replacing default DMEM *vhd file with simulation-optimized one..." |
echo "" |
rm -rf $homedir/riscv-arch-test/work/neorv32/rtl/core/neorv32_dmem.vhd |
cp $homedir/riscv-arch-test/work/neorv32/sim/rtl_modules/neorv32_dmem.vhd $homedir/riscv-arch-test/work/neorv32/rtl/core/. |
|
# Make a local copy of the original IMEM rtl file |
echo "" |
echo ">>> Making local backup of original IMEM rtl file (work/neorv32/rtl/core/neorv32_imem.ORIGINAL)..." |
echo "" |
cp $homedir/riscv-arch-test/work/neorv32/rtl/core/neorv32_imem.vhd $homedir/riscv-arch-test/work/neorv32/rtl/core/neorv32_imem.ORIGINAL |
|
# Component installation done |
ls -al |
echo "--------------------------------------------------------------------------" |
echo "> Component installation done!" |
echo "--------------------------------------------------------------------------" |
echo "" |
|
|
# neorv32 home folder |
NEORV32_LOCAL_HOME=$homedir/riscv-arch-test/work/neorv32 |
|
echo "--------------------------------------------------------------------------" |
echo "> Starting RISC-V architecture tests..." |
echo "--------------------------------------------------------------------------" |
|
# Clean everything |
make -C $homedir/riscv-arch-test/work/riscv-arch-test NEORV32_LOCAL_COPY=$NEORV32_LOCAL_HOME XLEN=32 RISCV_TARGET=neorv32 clean |
|
# Run tests and check results |
make --silent -C $homedir/riscv-arch-test/work/riscv-arch-test NEORV32_LOCAL_COPY=$NEORV32_LOCAL_HOME SIM_TIME=600us XLEN=32 RISCV_TARGET=neorv32 RISCV_DEVICE=I build run verify |
make --silent -C $homedir/riscv-arch-test/work/riscv-arch-test NEORV32_LOCAL_COPY=$NEORV32_LOCAL_HOME SIM_TIME=400us XLEN=32 RISCV_TARGET=neorv32 RISCV_DEVICE=C build run verify |
make --silent -C $homedir/riscv-arch-test/work/riscv-arch-test NEORV32_LOCAL_COPY=$NEORV32_LOCAL_HOME SIM_TIME=800us XLEN=32 RISCV_TARGET=neorv32 RISCV_DEVICE=M build run verify |
make --silent -C $homedir/riscv-arch-test/work/riscv-arch-test NEORV32_LOCAL_COPY=$NEORV32_LOCAL_HOME SIM_TIME=200us XLEN=32 RISCV_TARGET=neorv32 RISCV_DEVICE=privilege build run verify |
make --silent -C $homedir/riscv-arch-test/work/riscv-arch-test NEORV32_LOCAL_COPY=$NEORV32_LOCAL_HOME SIM_TIME=200us XLEN=32 RISCV_TARGET=neorv32 RISCV_DEVICE=Zifencei RISCV_TARGET_FLAGS=-DNEORV32_NO_DATA_INIT build run verify |
|
echo "" |
echo "RISC-V architecture tests completed successfully" |
/neorv32/trunk/rtl/core/neorv32_cfs.vhd
45,7 → 45,9
|
entity neorv32_cfs is |
generic ( |
CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000" -- custom CFS configuration conduit generic |
CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic |
CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits |
CFS_OUT_SIZE : positive := 32 -- size of CFS output conduit in bits |
); |
port ( |
-- host access -- |
66,8 → 68,8
irq_o : out std_ulogic; -- interrupt request |
irq_ack_i : in std_ulogic; -- interrupt acknowledge |
-- custom io (conduits) -- |
cfs_in_i : in std_ulogic_vector(31 downto 0); -- custom inputs |
cfs_out_o : out std_ulogic_vector(31 downto 0) -- custom outputs |
cfs_in_i : in std_ulogic_vector(CFS_IN_SIZE-1 downto 0); -- custom inputs |
cfs_out_o : out std_ulogic_vector(CFS_OUT_SIZE-1 downto 0) -- custom outputs |
); |
end neorv32_cfs; |
|
100,10 → 102,12
rden <= acc_en and rden_i; -- the read access is always a full 32-bit word wide; if required, the byte/half-word select/masking is done in the CPU |
|
|
-- CFS Generic ---------------------------------------------------------------------------- |
-- CFS Generics --------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- In its default version, the CFS provides a single generic: CFS_CONFIG. This generic can be set using the processor top's IO_CFS_CONFIG generic. |
-- It is intended as a "conduit" to propagate custom implementation option from the top down to this entiy. |
-- In its default version, the CFS provides the configuration generics. single generic: |
-- CFS_IN_SIZE configures the size (in bits) of the CFS input conduit cfs_in_i |
-- CFS_OUT_SIZE configures the size (in bits) of the CFS output conduit cfs_out_o |
-- CFS_CONFIG is a blank 32-bit generic. It is intended as a "generic conduit" to propagate custom configuration flags from the top entity down to this entiy. |
|
|
-- CFS IOs -------------------------------------------------------------------------------- |
206,7 → 210,7
-- ack_o <= ... -- or define the ACK by yourself (example: some registers are read-only, some others can only be written, ...) |
|
-- write access -- |
for i in 0 to 3 loop -- iterate over all 4 bytes in a word |
for i in 0 to 3 loop |
if (wren = '1') then -- word-wide write-access only! |
case addr is -- make sure to use the internal 'addr' signal for the read/write interface |
when cfs_reg0_addr_c => cfs_reg_wr(0) <= data_i; -- for example: control register |
/neorv32/trunk/rtl/core/neorv32_cpu.vhd
5,7 → 5,9
-- # * neorv32_cpu.vhd - CPU top entity # |
-- # * neorv32_cpu_alu.vhd - Arithmetic/logic unit # |
-- # * neorv32_cpu_bus.vhd - Instruction and data bus interface unit # |
-- # * neorv32_cpu_cp_muldiv.vhd - MULDIV co-processor # |
-- # * neorv32_cpu_cp_bitmanip.vhd - Bit-manipulation co-processor ('B') # |
-- # * neorv32_cpu_cp_fpu.vhd - Single-precision FPU co-processor ('F') # |
-- # * neorv32_cpu_cp_muldiv.vhd - Integer multiplier/divider co-processor ('M') # |
-- # * neorv32_cpu_ctrl.vhd - CPU control and CSR system # |
-- # * neorv32_cpu_decompressor.vhd - Compressed instructions decoder # |
-- # * neorv32_cpu_regfile.vhd - Data register file # |
62,10 → 64,11
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions? |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_F : boolean := false; -- implement 32-bit floating-point extension? |
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.? |
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.? |
-- Extension Options -- |
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
121,27 → 124,31
architecture neorv32_cpu_rtl of neorv32_cpu is |
|
-- local signals -- |
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus |
signal comparator : std_ulogic_vector(1 downto 0); -- comparator result |
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate |
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction |
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers |
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result |
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu address result |
signal rdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory read data |
signal alu_wait : std_ulogic; -- alu is busy due to iterative unit |
signal bus_i_wait : std_ulogic; -- wait for current bus instruction fetch |
signal bus_d_wait : std_ulogic; -- wait for current bus data access |
signal csr_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data |
signal mar : std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register |
signal ma_instr : std_ulogic; -- misaligned instruction address |
signal ma_load : std_ulogic; -- misaligned load data address |
signal ma_store : std_ulogic; -- misaligned store data address |
signal be_instr : std_ulogic; -- bus error on instruction access |
signal be_load : std_ulogic; -- bus error on load data access |
signal be_store : std_ulogic; -- bus error on store data access |
signal fetch_pc : std_ulogic_vector(data_width_c-1 downto 0); -- pc for instruction fetch |
signal curr_pc : std_ulogic_vector(data_width_c-1 downto 0); -- current pc (for current executed instruction) |
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus |
signal comparator : std_ulogic_vector(1 downto 0); -- comparator result |
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate |
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction |
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers |
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result |
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu address result |
signal mem_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory read data |
signal mem_wdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory write-data |
signal alu_wait : std_ulogic; -- alu is busy due to iterative unit |
signal bus_i_wait : std_ulogic; -- wait for current bus instruction fetch |
signal bus_d_wait : std_ulogic; -- wait for current bus data access |
signal csr_rdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data |
signal mar : std_ulogic_vector(data_width_c-1 downto 0); -- current memory address register |
signal ma_instr : std_ulogic; -- misaligned instruction address |
signal ma_load : std_ulogic; -- misaligned load data address |
signal ma_store : std_ulogic; -- misaligned store data address |
signal be_instr : std_ulogic; -- bus error on instruction access |
signal be_load : std_ulogic; -- bus error on load data access |
signal be_store : std_ulogic; -- bus error on store data access |
signal fetch_pc : std_ulogic_vector(data_width_c-1 downto 0); -- pc for instruction fetch |
signal curr_pc : std_ulogic_vector(data_width_c-1 downto 0); -- current pc (for current executed instruction) |
signal fpu_mem_wdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory write-data form FPU |
signal fpu_rm : std_ulogic_vector(2 downto 0); -- FPU rounding mode |
signal fpu_flags : std_ulogic_vector(4 downto 0); -- FPU exception flags |
|
-- co-processor interface -- |
signal cp_start : std_ulogic_vector(7 downto 0); -- trigger co-processor i |
174,9 → 181,12
-- A extension - only lr.w and sc.w are supported yet -- |
assert not (CPU_EXTENSION_RISCV_A = true) report "NEORV32 CPU CONFIG WARNING! Atomic operations extension (A) only supports <lr.w> and <sc.w> instructions." severity warning; |
|
-- Bit manipulation notifier -- |
assert not (CPU_EXTENSION_RISCV_B = true) report "NEORV32 CPU CONFIG WARNING! Bit manipulation extension (B) is still highly experimental (not ratified yet)." severity warning; |
-- FIXME: Bit manipulation warning -- |
assert not (CPU_EXTENSION_RISCV_B = true) report "NEORV32 CPU CONFIG WARNING! Bit manipulation extension (B) is still HIGHLY EXPERIMENTAL (and spec. is not ratified yet)." severity warning; |
|
-- FIXME: Floating-point extension warning -- |
assert not (CPU_EXTENSION_RISCV_F = true) report "NEORV32 CPU CONFIG WARNING! 32-bit floating-point extension (F) is WORK-IN-PROGRESS and NOT OPERATIONAL yet." severity warning; |
|
-- PMP regions check -- |
assert not (PMP_NUM_REGIONS > 64) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions <PMP_NUM_REGIONS> out of valid range (0..64)." severity error; |
-- PMP granulartiy -- |
205,6 → 215,7
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit manipulation extensions? |
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension? |
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_F => CPU_EXTENSION_RISCV_F, -- implement 32-bit floating-point extension? |
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system? |
234,6 → 245,9
fetch_pc_o => fetch_pc, -- PC for instruction fetch |
curr_pc_o => curr_pc, -- current PC (corresponding to current instruction) |
csr_rdata_o => csr_rdata, -- CSR read data |
-- FPU interface -- |
fpu_rm_o => fpu_rm, -- rounding mode |
fpu_flags_i => fpu_flags, -- exception flags |
-- interrupts (risc-v compliant) -- |
msw_irq_i => msw_irq_i, -- machine software interrupt |
mext_irq_i => mext_irq_i, -- machine external interrupt |
271,7 → 285,7
clk_i => clk_i, -- global clock, rising edge |
ctrl_i => ctrl, -- main control bus |
-- data input -- |
mem_i => rdata, -- memory read data |
mem_i => mem_rdata, -- memory read data |
alu_i => alu_res, -- ALU result |
-- data output -- |
rs1_o => rs1, -- operand 1 |
396,11 → 410,40
cp_valid(3) <= cp_start(3); -- always assigned even if Zicsr extension is disabled to make sure CPU does not get stalled if there is an accidental access |
|
|
-- Co-Processor 4..7: Not Implemented Yet ------------------------------------------------- |
-- Co-Processor 4: Single-Precision Floating-Point Unit ('F' Extension) ------------------- |
-- ------------------------------------------------------------------------------------------- |
cp_result(4) <= (others => '0'); |
cp_valid(4) <= '0'; |
-- |
neorv32_cpu_cp_fpu_inst_true: |
if (CPU_EXTENSION_RISCV_F = true) generate |
neorv32_cpu_cp_fpu_inst: neorv32_cpu_cp_fpu |
port map ( |
-- global control -- |
clk_i => clk_i, -- global clock, rising edge |
rstn_i => rstn_i, -- global reset, low-active, async |
ctrl_i => ctrl, -- main control bus |
start_i => cp_start(4), -- trigger operation |
-- data input -- |
frm_i => fpu_rm, -- rounding mode |
reg_i => rs1, -- rf source |
mem_i => mem_rdata, -- memory read-data |
-- result and status -- |
fflags_o => fpu_flags, -- exception flags |
mem_o => fpu_mem_wdata, -- memory write-data |
res_o => cp_result(4), -- operation result |
valid_o => cp_valid(4) -- data output valid |
); |
end generate; |
|
neorv32_cpu_cp_fpu_inst_false: |
if (CPU_EXTENSION_RISCV_F = false) generate |
fpu_flags <= (others => '0'); |
fpu_mem_wdata <= (others => '0'); |
cp_result(4) <= (others => '0'); |
cp_valid(4) <= cp_start(4); -- to make sure CPU does not get stalled if there is an accidental access |
end generate; |
|
|
-- Co-Processor 5..7: Not Implemented Yet ------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
cp_result(5) <= (others => '0'); |
cp_valid(5) <= '0'; |
-- |
436,8 → 479,8
be_instr_o => be_instr, -- bus error on instruction access |
-- cpu data access interface -- |
addr_i => alu_add, -- ALU.add result -> access address |
wdata_i => rs2, -- write data |
rdata_o => rdata, -- read data |
wdata_i => mem_wdata, -- write data |
rdata_o => mem_rdata, -- read data |
mar_o => mar, -- current memory address register |
d_wait_o => bus_d_wait, -- wait for access to complete |
-- |
474,6 → 517,9
d_bus_lock_o => d_bus_lock_o -- locked/exclusive access |
); |
|
-- memory write data -- |
mem_wdata <= fpu_mem_wdata when ((CPU_EXTENSION_RISCV_F = true) and (ctrl(ctrl_bus_wd_sel_c) = '1')) else rs2; |
|
-- current privilege level -- |
i_bus_priv_o <= ctrl(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c); |
d_bus_priv_o <= ctrl(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c); |
/neorv32/trunk/rtl/core/neorv32_cpu_control.vhd
55,6 → 55,7
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions? |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_F : boolean := false; -- implement 32-bit floating-point extension? |
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system? |
84,6 → 85,9
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch |
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction) |
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data |
-- FPU interface -- |
fpu_rm_o : out std_ulogic_vector(02 downto 0); -- rounding mode |
fpu_flags_i : in std_ulogic_vector(04 downto 0); -- exception flags |
-- interrupts (risc-v compliant) -- |
msw_irq_i : in std_ulogic; -- machine software interrupt |
mext_irq_i : in std_ulogic; -- machine external interrupt |
176,6 → 180,8
is_atomic_sc : std_ulogic; |
is_bitmanip_imm : std_ulogic; |
is_bitmanip_reg : std_ulogic; |
is_float_f_reg : std_ulogic; |
is_float_i_reg : std_ulogic; |
sys_env_cmd : std_ulogic_vector(11 downto 0); |
end record; |
signal decode_aux : decode_aux_t; |
196,6 → 202,8
is_ci_nxt : std_ulogic; |
is_cp_op : std_ulogic; -- current instruction is a co-processor operation |
is_cp_op_nxt : std_ulogic; |
is_fp : std_ulogic; -- floating-point operation - do not access to integer register file |
is_fp_nxt : std_ulogic; |
-- |
branch_taken : std_ulogic; -- branch condition fullfilled |
pc : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction |
322,6 → 330,9
pmpcfg_rd : pmp_ctrl_rd_t; -- physical memory protection - actual read data |
pmpaddr : pmp_addr_t; -- physical memory protection - address registers |
pmpaddr_rd : pmp_addr_rd_t; -- physical memory protection - actual read data |
-- |
frm : std_ulogic_vector(02 downto 0); -- frm (R/W): FPU rounding mode |
fflags : std_ulogic_vector(04 downto 0); -- fflags (R/W): FPU exception flags |
end record; |
signal csr : csr_t; |
|
606,7 → 617,7
imm_o <= execute_engine.next_pc; |
else -- "normal" immediate from instruction word |
case opcode_v is -- save some bits here, the two LSBs are always "11" for rv32 |
when opcode_store_c => -- S-immediate |
when opcode_store_c | opcode_fsw_c => -- S-immediate |
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension |
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25); |
imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08); |
695,6 → 706,7
execute_engine.i_reg <= execute_engine.i_reg_nxt; |
execute_engine.is_ci <= execute_engine.is_ci_nxt; |
execute_engine.is_cp_op <= execute_engine.is_cp_op_nxt; |
execute_engine.is_fp <= execute_engine.is_fp_nxt; |
-- PC & IR of "last executed" instruction -- |
if (execute_engine.state = EXECUTE) then |
execute_engine.last_pc <= execute_engine.pc; |
768,6 → 780,8
decode_aux.is_atomic_sc <= '0'; |
decode_aux.is_bitmanip_imm <= '0'; |
decode_aux.is_bitmanip_reg <= '0'; |
decode_aux.is_float_f_reg <= '0'; |
decode_aux.is_float_i_reg <= '0'; |
|
-- is immediate ALU operation? -- |
decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1); |
776,7 → 790,7
decode_aux.rs1_is_r0 <= not or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); |
|
-- is atomic load-reservate/store-conditional? -- |
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') then -- valid atomic sub-opcode |
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "11") then -- valid atomic sub-opcode |
decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c); |
decode_aux.is_atomic_sc <= execute_engine.i_reg(instr_funct5_lsb_c); |
end if; |
820,6 → 834,26
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) then -- SBSEXT |
decode_aux.is_bitmanip_reg <= '1'; |
end if; |
|
-- floating-point FLOAT_register operations -- |
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11110")) or -- FMV.W.X |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00000")) or -- FADD.S |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00001")) or -- FSUB.S |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00011")) or -- FDIV.S |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01011") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00000")) or -- FSQRT.S |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_msb_c-1) = "00")) or -- FMIN.S / FMAX.S |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11010") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.S.W* |
decode_aux.is_float_f_reg <= '1'; |
end if; |
-- floating-point INTEGER_register operations -- |
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_msb_c-1) = "00")) or -- FMV.X.W / FCLASS.S |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "10100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FEQ.S / FLT.S / FLE.S |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11000") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.W*.S |
decode_aux.is_float_i_reg <= '1'; |
end if; |
|
-- system/environment instructions -- |
sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c; -- sum-up set bits |
decode_aux.sys_env_cmd(11 downto 0) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unsued bits to always-zero |
837,6 → 871,7
execute_engine.i_reg_nxt <= execute_engine.i_reg; |
execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op; |
execute_engine.is_ci_nxt <= execute_engine.is_ci; |
execute_engine.is_fp_nxt <= execute_engine.is_fp; |
execute_engine.sleep_nxt <= execute_engine.sleep; |
execute_engine.branched_nxt <= execute_engine.branched; |
-- |
897,6 → 932,9
|
when DISPATCH => -- Get new command from instruction issue engine |
-- ------------------------------------------------------------ |
-- housekeeping -- |
execute_engine.is_cp_op_nxt <= '0'; -- init |
execute_engine.is_fp_nxt <= '0'; -- init |
-- PC update -- |
execute_engine.pc_mux_sel <= '0'; -- linear next PC |
-- IR update -- |
1026,13 → 1064,19
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back |
execute_engine.state_nxt <= DISPATCH; |
|
when opcode_load_c | opcode_store_c | opcode_atomic_c => -- load/store / atomic memory access |
when opcode_load_c | opcode_store_c | opcode_atomic_c | opcode_flw_c | opcode_fsw_c => -- load/store / atomic memory access / floating-point load/store |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA |
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB |
ctrl_nxt(ctrl_bus_mo_we_c) <= '1'; -- write to MAR and MDO (MDO only relevant for store) |
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "01") then -- floating-point load/store |
execute_engine.is_fp_nxt <= decode_aux.is_float_f_reg; -- no integer register file write back for FPU internal operations |
ctrl_nxt(ctrl_bus_wd_sel_c) <= '1'; -- use memory-write-data from FPU co-processor (only relevant for float STORE) |
end if; |
-- |
if (CPU_EXTENSION_RISCV_A = false) or (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') then -- atomic (A) extension disabled or normal load/store |
if (CPU_EXTENSION_RISCV_A = false) or -- atomic extension disabled |
(execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "00") or -- normal integerload/store |
((CPU_EXTENSION_RISCV_F = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "01")) then -- floating-point load/store |
execute_engine.state_nxt <= LOADSTORE_0; |
else -- atomic operation |
atomic_ctrl.env_start <= not execute_engine.i_reg(instr_funct5_lsb_c); -- LR: start LOCKED memory access environment |
1074,6 → 1118,17
execute_engine.state_nxt <= SYS_WAIT; |
end if; |
|
when opcode_fop_c => -- floating-point operations (1 or 2 operands) |
-- ------------------------------------------------------------ |
execute_engine.state_nxt <= SYS_WAIT; |
if (CPU_EXTENSION_RISCV_F = true) then |
execute_engine.is_fp_nxt <= decode_aux.is_float_f_reg; -- no integer register file write back for FPU internal operations |
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_fpu_c; -- use FPU CP |
execute_engine.is_cp_op_nxt <= '1'; -- this is a CP operation |
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; |
execute_engine.state_nxt <= ALU_WAIT; |
end if; |
|
when others => -- undefined |
-- ------------------------------------------------------------ |
execute_engine.state_nxt <= SYS_WAIT; |
1114,7 → 1169,11
when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back) |
if (CPU_EXTENSION_RISCV_F = false) then |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back) |
else |
ctrl_nxt(ctrl_rf_wb_en_c) <= not execute_engine.is_fp; -- allow write back if NOT <FPU-internal operation> |
end if; |
-- cp access or alu.shift? -- |
if (execute_engine.is_cp_op = '1') then |
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; |
1204,8 → 1263,11
execute_engine.state_nxt <= DISPATCH; |
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction |
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') or (decode_aux.is_atomic_sc = '1') then -- load / load-reservate / store conditional |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back |
ctrl_nxt(ctrl_rf_wb_en_c) <= not execute_engine.is_fp; -- allow write back if NOT <FPU-internal operation> |
end if; |
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) = opcode_flw_c(6 downto 2)) then -- floating-point LOAD.word |
ctrl_nxt(ctrl_cp_fpu_mem_we_c) <= '1'; -- co-processor register file write-back |
end if; |
atomic_ctrl.env_end <= not decode_aux.is_atomic_lr; -- normal end of LOCKED (atomic) memory access environment - if we are not starting it via LR instruction |
execute_engine.state_nxt <= DISPATCH; |
end if; |
1243,13 → 1305,17
|
-- low privilege level access to hpm counters? -- |
csr_mcounteren_hpm_v := (others => '0'); |
if (CPU_EXTENSION_RISCV_U = true) then -- 'mcounteren' CSR is hardwired to zero if user mode is not implemented |
if (CPU_EXTENSION_RISCV_U = true) then |
csr_mcounteren_hpm_v(HPM_NUM_CNTS-1 downto 0) := csr.mcounteren_hpm(HPM_NUM_CNTS-1 downto 0); |
else -- 'mcounteren' CSR is hardwired to zero if user mode is not implemented |
csr_mcounteren_hpm_v := (others => '0'); |
end if; |
|
-- check CSR access -- |
case csr.addr is |
-- standard read/write CSRs -- |
when csr_fflags_c | csr_frm_c | csr_fcsr_c => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_F); -- full access for everyone if F extension is enabled |
-- |
when csr_mstatus_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_mstatush_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_misa_c => csr_acc_valid <= csr.priv_m_mode;-- and (not csr_wacc_v); -- M-mode only, MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility |
1410,6 → 1476,7
case opcode_v is |
|
-- check sufficient LUI, UIPC, JAL (only check actual OPCODE) -- |
-- ------------------------------------------------------------ |
when opcode_lui_c | opcode_auipc_c | opcode_jal_c => |
illegal_instruction <= '0'; |
-- illegal E-CPU register? -- |
1418,6 → 1485,7
end if; |
|
when opcode_alu_c => -- check ALU.funct3 & ALU.funct7 |
-- ------------------------------------------------------------ |
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV |
if (CPU_EXTENSION_RISCV_M = false) then -- not implemented |
illegal_instruction <= '1'; |
1441,6 → 1509,7
end if; |
|
when opcode_alui_c => -- check ALUI.funct7 |
-- ------------------------------------------------------------ |
if (decode_aux.is_bitmanip_imm = '1') then -- bit manipulation |
if (CPU_EXTENSION_RISCV_B = false) then -- not implemented |
illegal_instruction <= '1'; |
1460,6 → 1529,7
end if; |
|
when opcode_load_c => -- check LOAD.funct3 |
-- ------------------------------------------------------------ |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or |
1475,6 → 1545,7
end if; |
|
when opcode_store_c => -- check STORE.funct3 |
-- ------------------------------------------------------------ |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then |
1488,6 → 1559,7
end if; |
|
when opcode_branch_c => -- check BRANCH.funct3 |
-- ------------------------------------------------------------ |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or |
1504,6 → 1576,7
end if; |
|
when opcode_jalr_c => -- check JALR.funct3 |
-- ------------------------------------------------------------ |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then |
illegal_instruction <= '0'; |
else |
1514,7 → 1587,8
illegal_register <= '1'; |
end if; |
|
when opcode_fence_c => -- fence instructions -- |
when opcode_fence_c => -- fence instructions |
-- ------------------------------------------------------------ |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I |
illegal_instruction <= '0'; |
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE |
1523,7 → 1597,8
illegal_instruction <= '1'; |
end if; |
|
when opcode_syscsr_c => -- check system instructions -- |
when opcode_syscsr_c => -- check system instructions |
-- ------------------------------------------------------------ |
-- CSR access -- |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or |
1561,7 → 1636,8
illegal_instruction <= '1'; |
end if; |
|
when opcode_atomic_c => -- atomic instructions -- |
when opcode_atomic_c => -- atomic instructions |
-- ------------------------------------------------------------ |
if (CPU_EXTENSION_RISCV_A = true) and -- atomic memory operations (A extension) enabled |
((execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) or -- LR |
(execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c)) then -- SC |
1570,7 → 1646,27
illegal_instruction <= '1'; |
end if; |
|
when opcode_fop_c => -- floating point operations (dual-operand) |
-- ------------------------------------------------------------ |
if (CPU_EXTENSION_RISCV_F = true) and -- F extension enabled |
(execute_engine.i_reg(instr_funct7_lsb_c+1 downto instr_funct7_lsb_c) = float_single_c) and -- single-precision operations |
((decode_aux.is_float_f_reg = '1') or (decode_aux.is_float_i_reg = '1')) then -- float_reg or int_reg operations |
illegal_instruction <= '0'; |
else |
illegal_instruction <= '1'; |
end if; |
|
when opcode_flw_c | opcode_fsw_c => -- floating point load/store word |
-- ------------------------------------------------------------ |
if (CPU_EXTENSION_RISCV_F = true) and -- F extension enabled |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") then -- 32-bit transfer size |
illegal_instruction <= '0'; |
else |
illegal_instruction <= '1'; |
end if; |
|
when others => -- undefined instruction -> illegal! |
-- ------------------------------------------------------------ |
illegal_instruction <= '1'; |
|
end case; |
1870,10 → 1966,9
end process csr_write_data; |
|
|
-- Control and Status Registers Write Access ---------------------------------------------- |
-- Control and Status Registers - Write Access -------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
csr_write_access: process(rstn_i, clk_i) |
variable pmpaddr_v : std_ulogic_vector(6 downto 0); |
begin |
if (rstn_i = '0') then |
csr.we <= '0'; |
1890,23 → 1985,25
csr.mscratch <= x"19880704"; -- :) |
csr.mepc <= (others => '0'); |
csr.mcause <= trap_reset_c; -- mcause = TRAP_CODE_RESET (hardware reset, "non-maskable interrupt") |
-- |
csr.mtval <= (others => '0'); |
csr.mip_clear <= (others => '0'); |
-- |
csr.pmpcfg <= (others => (others => '0')); |
csr.pmpaddr <= (others => (others => '1')); |
csr.pmpcfg <= (others => (others => '0')); |
csr.pmpaddr <= (others => (others => '1')); |
-- |
csr.mhpmevent <= (others => (others => '0')); |
csr.mhpmevent <= (others => (others => '0')); |
-- |
csr.mcounteren_cy <= '0'; |
csr.mcounteren_tm <= '0'; |
csr.mcounteren_ir <= '0'; |
csr.mcounteren_hpm <= (others => '0'); |
csr.mcounteren_cy <= '0'; |
csr.mcounteren_tm <= '0'; |
csr.mcounteren_ir <= '0'; |
csr.mcounteren_hpm <= (others => '0'); |
-- |
csr.mcountinhibit_cy <= '0'; |
csr.mcountinhibit_ir <= '0'; |
csr.mcountinhibit_hpm <= (others => '0'); |
-- |
csr.fflags <= (others => '0'); |
csr.frm <= (others => '0'); |
|
elsif rising_edge(clk_i) then |
-- write access? -- |
1920,11 → 2017,30
-- CSR access by application software |
-- -------------------------------------------------------------------------------- |
if (csr.we = '1') then -- manual update |
case csr.addr is |
|
-- machine trap setup -- |
-- -------------------------------------------------------------------- |
when csr_mstatus_c => -- R/W: mstatus - machine status register |
|
-- user floating-point CSRs -- |
-- -------------------------------------------------------------------- |
if (csr.addr(11 downto 4) = csr_class_float_c) then -- floating point CSR class |
-- R/W: fflags - floating-point (FPU) exception flags -- |
if (csr.addr(3 downto 0) = csr_fflags_c(3 downto 0)) and (CPU_EXTENSION_RISCV_F = true) then |
csr.fflags <= csr.wdata(4 downto 0); |
end if; |
-- R/W: frm - floating-point (FPU) rounding mode -- |
if (csr.addr(3 downto 0) = csr_frm_c(3 downto 0)) and (CPU_EXTENSION_RISCV_F = true) then |
csr.frm <= csr.wdata(2 downto 0); |
end if; |
-- R/W: fflags - floating-point (FPU) control/status (frm + fflags) -- |
if (csr.addr(3 downto 0) = csr_fcsr_c(3 downto 0)) and (CPU_EXTENSION_RISCV_F = true) then |
csr.frm <= csr.wdata(7 downto 5); |
csr.fflags <= csr.wdata(4 downto 0); |
end if; |
end if; |
|
-- machine trap setup -- |
-- -------------------------------------------------------------------- |
if (csr.addr(11 downto 4) = csr_setup_c) then -- ftrap setup CSR class |
-- R/W: mstatus - machine status register -- |
if (csr.addr(3 downto 0) = csr_mstatus_c(3 downto 0)) then |
csr.mstatus_mie <= csr.wdata(03); |
csr.mstatus_mpie <= csr.wdata(07); |
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented |
1933,7 → 2049,9
else -- only machine mode is available |
csr.mstatus_mpp <= priv_mode_m_c; |
end if; |
when csr_mie_c => -- R/W: mie - machine interrupt enable register |
end if; |
-- R/W: mie - machine interrupt enable register -- |
if (csr.addr(3 downto 0) = csr_mie_c(3 downto 0)) then |
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable |
csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable |
csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable |
1940,30 → 2058,44
for i in 0 to 15 loop -- fast interrupt channels 0..15 |
csr.mie_firqe(i) <= csr.wdata(16+i); |
end loop; -- i |
when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions) |
end if; |
-- R/W: mtvec - machine trap-handler base address (for ALL exceptions) -- |
if (csr.addr(3 downto 0) = csr_mtvec_c(3 downto 0)) then |
csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0 |
when csr_mcounteren_c => -- R/W: machine counter enable register |
end if; |
-- R/W: machine counter enable register -- |
if (csr.addr(3 downto 0) = csr_mcounteren_c(3 downto 0)) then |
if (CPU_EXTENSION_RISCV_U = true) then -- this CSR is hardwired to zero if user mode is not implemented |
csr.mcounteren_cy <= csr.wdata(0); -- enable user-level access to cycle[h] |
csr.mcounteren_tm <= csr.wdata(1); -- enable user-level access to time[h] |
csr.mcounteren_ir <= csr.wdata(2); -- enable user-level access to instret[h] |
csr.mcounteren_hpm <= csr.wdata(csr.mcounteren_hpm'left+3 downto 3); -- enable user-level access to hpmcounterx[h] |
else |
NULL; |
end if; |
end if; |
end if; |
|
-- machine trap handling -- |
-- -------------------------------------------------------------------- |
when csr_mscratch_c => -- R/W: mscratch - machine scratch register |
-- machine trap handling -- |
-- -------------------------------------------------------------------- |
if (csr.addr(11 downto 4) = csr_class_trap_c) then -- machine trap handling CSR class |
-- R/W: mscratch - machine scratch register -- |
if (csr.addr(3 downto 0) = csr_mscratch_c(3 downto 0)) then |
csr.mscratch <= csr.wdata; |
when csr_mepc_c => -- R/W: mepc - machine exception program counter |
end if; |
-- R/W: mepc - machine exception program counter -- |
if (csr.addr(3 downto 0) = csr_mepc_c(3 downto 0)) then |
csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0'; |
when csr_mcause_c => -- R/W: mcause - machine trap cause |
end if; |
-- R/W: mcause - machine trap cause -- |
if (csr.addr(3 downto 0) = csr_mcause_c(3 downto 0)) then |
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception |
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier |
when csr_mtval_c => -- R/W: mtval - machine bad address/instruction |
end if; |
-- R/W: mtval - machine bad address/instruction -- |
if (csr.addr(3 downto 0) = csr_mtval_c(3 downto 0)) then |
csr.mtval <= csr.wdata; |
when csr_mip_c => -- R/W: mip - machine interrupt pending |
end if; |
-- R/W: mip - machine interrupt pending -- |
if (csr.addr(3 downto 0) = csr_mip_c(3 downto 0)) then |
csr.mip_clear(interrupt_msw_irq_c) <= not csr.wdata(03); |
csr.mip_clear(interrupt_mtime_irq_c) <= not csr.wdata(07); |
csr.mip_clear(interrupt_mext_irq_c) <= not csr.wdata(11); |
1970,89 → 2102,78
for i in 0 to 15 loop -- fast interrupt channels 0..15 |
csr.mip_clear(interrupt_firq_0_c+i) <= not csr.wdata(16+i); |
end loop; -- i |
end if; |
end if; |
|
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers -- |
-- -------------------------------------------------------------------- |
when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c | csr_pmpcfg4_c | csr_pmpcfg5_c | csr_pmpcfg6_c | csr_pmpcfg7_c | |
csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c => |
if (PMP_NUM_REGIONS > 0) then |
for i in 0 to PMP_NUM_REGIONS-1 loop |
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then |
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access |
csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read) |
csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W (rights.write) |
csr.pmpcfg(i)(2) <= csr.wdata((i mod 4)*8+2); -- X (rights.execute) |
csr.pmpcfg(i)(3) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_L |
csr.pmpcfg(i)(4) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_H - NAPOT/OFF only |
csr.pmpcfg(i)(5) <= '0'; -- reserved |
csr.pmpcfg(i)(6) <= '0'; -- reserved |
csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode) |
end if; |
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers -- |
-- -------------------------------------------------------------------- |
if (csr.addr(11 downto 4) = csr_class_pmpcfg_c) then -- pmp configuration CSR class |
if (PMP_NUM_REGIONS > 0) then |
for i in 0 to PMP_NUM_REGIONS-1 loop |
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then |
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access |
csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read) |
csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W (rights.write) |
csr.pmpcfg(i)(2) <= csr.wdata((i mod 4)*8+2); -- X (rights.execute) |
csr.pmpcfg(i)(3) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_L |
csr.pmpcfg(i)(4) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_H - NAPOT/OFF only |
csr.pmpcfg(i)(5) <= '0'; -- reserved |
csr.pmpcfg(i)(6) <= '0'; -- reserved |
csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode) |
end if; |
end loop; -- i (PMP regions) |
else |
NULL; |
end if; |
end if; |
end loop; -- i (PMP regions) |
end if; |
end if; |
|
-- physical memory protection: R/W: pmpaddr* - PMP address registers -- |
-- -------------------------------------------------------------------- |
when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c | |
csr_pmpaddr8_c | csr_pmpaddr9_c | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c | |
csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c | |
csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c | |
csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_c | |
csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c | |
csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c | |
csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c => |
if (PMP_NUM_REGIONS > 0) then |
for i in 0 to PMP_NUM_REGIONS-1 loop |
pmpaddr_v := std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i); -- adapt to *non-aligned* base address (csr_pmpaddr0_c) |
if (csr.addr(6 downto 0) = pmpaddr_v) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access |
csr.pmpaddr(i) <= csr.wdata; |
csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1'); |
end if; |
end loop; -- i (PMP regions) |
else |
NULL; |
end if; |
-- physical memory protection: R/W: pmpaddr* - PMP address registers -- |
-- -------------------------------------------------------------------- |
if (csr.addr(11 downto 4) = csr_pmpaddr0_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr16_c(11 downto 4)) or |
(csr.addr(11 downto 4) = csr_pmpaddr32_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr48_c(11 downto 4)) then |
if (PMP_NUM_REGIONS > 0) then |
for i in 0 to PMP_NUM_REGIONS-1 loop |
if (csr.addr(6 downto 0) = std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i)) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access |
csr.pmpaddr(i) <= csr.wdata; |
csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1'); |
end if; |
end loop; -- i (PMP regions) |
end if; |
end if; |
|
-- machine counter setup -- |
-- -------------------------------------------------------------------- |
when csr_mcountinhibit_c => -- R/W: mcountinhibit - machine counter-inhibit register |
csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter |
csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter |
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter |
-- machine counter setup -- |
-- -------------------------------------------------------------------- |
-- R/W: mcountinhibit - machine counter-inhibit register -- |
if (csr.addr = csr_mcountinhibit_c) then |
csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter |
csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter |
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter |
end if; |
|
-- machine performance-monitoring event selector -- |
-- -------------------------------------------------------------------- |
when csr_mhpmevent3_c | csr_mhpmevent4_c | csr_mhpmevent5_c | csr_mhpmevent6_c | csr_mhpmevent7_c | csr_mhpmevent8_c | |
csr_mhpmevent9_c | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c | |
csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c | |
csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c | |
csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c => -- R/W: mhpmevent* - machine performance-monitoring event selector |
if (HPM_NUM_CNTS > 0) then |
for i in 0 to HPM_NUM_CNTS-1 loop |
if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then |
csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0); |
csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME" |
end if; |
end loop; -- i (CSRs) |
else |
NULL; |
end if; |
-- machine performance-monitoring event selector -- |
-- -------------------------------------------------------------------- |
if (unsigned(csr.addr) >= unsigned(csr_mhpmevent3_c)) and (unsigned(csr.addr) <= unsigned(csr_mhpmevent31_c)) then |
if (HPM_NUM_CNTS > 0) then |
for i in 0 to HPM_NUM_CNTS-1 loop |
if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then |
csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0); |
csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME" |
end if; |
end loop; -- i (CSRs) |
end if; |
end if; |
|
-- undefined -- |
-- -------------------------------------------------------------------- |
when others => |
NULL; |
|
end case; |
|
-- -------------------------------------------------------------------------------- |
-- CSR access by hardware |
-- -------------------------------------------------------------------------------- |
else |
|
-- floating-point (FPU) exception flags -- |
-- -------------------------------------------------------------------- |
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.state = ALU_WAIT) then -- FIXME? |
csr.fflags <= csr.fflags or fpu_flags_i; -- accumulate flags ("accrued exception flags") |
end if; |
|
-- mcause, mepc, mtval: machine trap cause, PC and value register -- |
-- -------------------------------------------------------------------- |
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting? |
2103,9 → 2224,42
csr.mstatus_mpp <= priv_mode_m_c; |
end if; |
|
end if; -- hardware csr access |
end if; -- /hardware csr access |
end if; |
|
-- -------------------------------------------------------------------------------- |
-- override write access for disabled functions |
-- -------------------------------------------------------------------------------- |
|
-- user mode disabled -- |
if (CPU_EXTENSION_RISCV_U = false) then |
csr.privilege <= priv_mode_m_c; |
csr.mstatus_mpp <= priv_mode_m_c; |
csr.mcounteren_cy <= '0'; |
csr.mcounteren_tm <= '0'; |
csr.mcounteren_ir <= '0'; |
csr.mcounteren_hpm <= (others => '0'); |
end if; |
|
-- pmp disabled -- |
if (PMP_NUM_REGIONS = 0) then |
csr.pmpcfg <= (others => (others => '0')); |
csr.pmpaddr <= (others => (others => '1')); |
end if; |
|
-- hpms disabled -- |
if (HPM_NUM_CNTS = 0) then |
csr.mhpmevent <= (others => (others => '0')); |
csr.mcounteren_hpm <= (others => '0'); |
csr.mcountinhibit_hpm <= (others => '0'); |
end if; |
|
-- floating-point extension disabled -- |
if (CPU_EXTENSION_RISCV_F = false) then |
csr.fflags <= (others => '0'); |
csr.frm <= (others => '0'); |
end if; |
|
end if; |
end process csr_write_access; |
|
2139,7 → 2293,10
end loop; -- i |
end process pmp_rd_dummy; |
|
-- FPU rounding mode -- |
fpu_rm_o <= csr.frm; |
|
|
-- Control and Status Registers - Counters ------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
csr_counters: process(clk_i) |
2254,7 → 2411,7
cnt_event_nxt(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation |
|
|
-- Control and Status Registers Read Access ----------------------------------------------- |
-- Control and Status Registers - Read Access --------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
csr_read_access: process(clk_i) |
begin |
2264,6 → 2421,25
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then |
case csr.addr is |
|
-- user floating-point CSRs -- |
-- -------------------------------------------------------------------- |
when csr_fflags_c => -- R/W: fflags - floating-point (FPU) exception flags |
csr.rdata <= (others => '0'); |
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented |
csr.rdata(4 downto 0) <= csr.fflags; |
end if; |
when csr_frm_c => -- R/W: frm - floating-point (FPU) rounding mode |
csr.rdata <= (others => '0'); |
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented |
csr.rdata(2 downto 0) <= csr.frm; |
end if; |
when csr_fcsr_c => -- R/W: fflags - floating-point (FPU) control/status (frm + fflags) |
csr.rdata <= (others => '0'); |
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented |
csr.rdata(7 downto 5) <= csr.frm; |
csr.rdata(4 downto 0) <= csr.fflags; |
end if; |
|
-- machine trap setup -- |
when csr_mstatus_c => -- R/W: mstatus - machine status register |
csr.rdata(03) <= csr.mstatus_mie; -- MIE |
2278,6 → 2454,7
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension |
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension |
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension |
csr.rdata(05) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_F); -- F CPU extension |
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E) |
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension |
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension |
/neorv32/trunk/rtl/core/neorv32_cpu_cp_fpu.vhd
0,0 → 1,83
-- ################################################################################################# |
-- # << NEORV32 - CPU Co-Processor: Single-Precision Floating Point Unit (RISC-V "F" Extension) >> # |
-- # ********************************************************************************************* # |
-- # # |
-- # !!! WORK-IN-PROGRESS !!! # |
-- # !!! THIS UNIT IS NOT FUNCTIONAL YET !!! # |
-- # # |
-- # ********************************************************************************************* # |
-- # !!! Enabling the F extension does not has an effect on the CPU. If F is enabled, there !!! # |
-- # !!! will be no traps when trying to execute floating-point instructions, since the main !!! # |
-- # !!! CPU control unit allready provides all necessary F-extension infrastructure. !!! # |
-- # !!! However, all F instructions will always return zero. !!! # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. # |
-- # # |
-- # Redistribution and use in source and binary forms, with or without modification, are # |
-- # permitted provided that the following conditions are met: # |
-- # # |
-- # 1. Redistributions of source code must retain the above copyright notice, this list of # |
-- # conditions and the following disclaimer. # |
-- # # |
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
-- # conditions and the following disclaimer in the documentation and/or other materials # |
-- # provided with the distribution. # |
-- # # |
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
-- # endorse or promote products derived from this software without specific prior written # |
-- # permission. # |
-- # # |
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
-- # OF THE POSSIBILITY OF SUCH DAMAGE. # |
-- # ********************************************************************************************* # |
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # |
-- ################################################################################################# |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
library neorv32; |
use neorv32.neorv32_package.all; |
|
entity neorv32_cpu_cp_fpu is |
port ( |
-- global control -- |
clk_i : in std_ulogic; -- global clock, rising edge |
rstn_i : in std_ulogic; -- global reset, low-active, async |
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus |
start_i : in std_ulogic; -- trigger operation |
-- data input -- |
frm_i : in std_ulogic_vector(2 downto 0); -- rounding mode |
reg_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source (rs1) |
mem_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory read-data |
-- result and status -- |
fflags_o : out std_ulogic_vector(4 downto 0); -- exception flags |
mem_o : out std_ulogic_vector(data_width_c-1 downto 0); -- memory write-data |
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operation result |
valid_o : out std_ulogic -- data output valid |
); |
end neorv32_cpu_cp_fpu; |
|
architecture neorv32_cpu_cp_fpu_rtl of neorv32_cpu_cp_fpu is |
|
begin |
|
-- There is nothing to see here yet ------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
fflags_o <= (others => '0'); |
mem_o <= (others => '0'); |
res_o <= (others => '0'); |
valid_o <= start_i; |
|
|
end neorv32_cpu_cp_fpu_rtl; |
/neorv32/trunk/rtl/core/neorv32_cpu_decompressor.vhd
137,9 → 137,13
ci_instr32_o(instr_imm12_lsb_c + 9) <= ci_instr16_i(10); |
end if; |
|
when "010" => -- C.LW |
when "010" | "011" => -- C.LW / C.FLW |
-- ---------------------------------------------------------------------------------------------------------- |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c; |
if (ci_instr16_i(ci_funct3_lsb_c) = '0') then -- C.LW |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c; |
else -- C.FLW |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_flw_c; |
end if; |
ci_instr32_o(21 downto 20) <= "00"; |
ci_instr32_o(22) <= ci_instr16_i(6); |
ci_instr32_o(23) <= ci_instr16_i(10); |
151,9 → 155,13
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15 |
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c); -- x8 - x15 |
|
when "110" => -- C.SW |
when "110" | "111" => -- C.SW / C.FSW |
-- ---------------------------------------------------------------------------------------------------------- |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c; |
if (ci_instr16_i(ci_funct3_lsb_c) = '0') then -- C.SW |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c; |
else -- C.FSW |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_fsw_c; |
end if; |
ci_instr32_o(08 downto 07) <= "00"; |
ci_instr32_o(09) <= ci_instr16_i(6); |
ci_instr32_o(10) <= ci_instr16_i(10); |
362,9 → 370,13
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6); |
ci_illegal_o <= ci_instr16_i(12); |
|
when "010" => -- C.LWSP |
when "010" | "011" => -- C.LWSP / C.FLWSP |
-- ---------------------------------------------------------------------------------------------------------- |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c; |
if (ci_instr16_i(ci_funct3_lsb_c) = '0') then -- C.LWSP |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_load_c; |
else -- C.FLWSP |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_flw_c; |
end if; |
ci_instr32_o(21 downto 20) <= "00"; |
ci_instr32_o(22) <= ci_instr16_i(4); |
ci_instr32_o(23) <= ci_instr16_i(5); |
377,9 → 389,13
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer |
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c); |
|
when "110" => -- C.SWSP |
when "110" | "111" => -- C.SWSP / C.FSWSP |
-- ---------------------------------------------------------------------------------------------------------- |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c; |
if (ci_instr16_i(ci_funct3_lsb_c) = '0') then -- C.SWSP |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_store_c; |
else -- C.FSWSP |
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_fsw_c; |
end if; |
ci_instr32_o(08 downto 07) <= "00"; |
ci_instr32_o(09) <= ci_instr16_i(9); |
ci_instr32_o(10) <= ci_instr16_i(10); |
/neorv32/trunk/rtl/core/neorv32_neoled.vhd
0,0 → 1,394
-- ################################################################################################# |
-- # << NEORV32 - Smart LED (WS2811/WS2812) Interface (NEOLED) >> # |
-- # ********************************************************************************************* # |
-- # Hardware interface for direct control of "smart LEDs" using an asynchronouse serial data # |
-- # line. Compatible with the WS2811 and WS2812 LEDs. # |
-- # # |
-- # NeoPixel-compatible, RGB (24-bit) and RGBW (32-bit) # |
-- # (c) "NeoPixel" is a trademark of Adafruit Industries. # |
-- # # |
-- # The interface uses a programmable carries frequency (800 KHz for the WS2812 LEDs) # |
-- # configurable via the control register's clock prescaler bits (ctrl_clksel*_c) and the period # |
-- # length configuration bits (ctrl_t_tot_*_c). "high-times" for sending a ZERO or a ONE bit are # |
-- # configured using the ctrl_t_0h_*_c and ctrl_t_1h_*_c bits, respectively. 32-bit transfers # |
-- # (for RGBW modules) and 24-bit transfers (for RGB modules) are supported via ctrl_mode__c. # |
-- # # |
-- # The device features a TX buffer with <tx_buffer_entries_c> entries. The devices busy flag and # |
-- # IRQ generator can be programmed to either clear the busy flag / send an IRQ when AT LEAST ONE # |
-- # FREE BUFFER ENTRY is available (ctrl_bscon_c = 0) or when the WHOLE BUFFER IS EMPTY # |
-- # (ctrl_bscon_c = 1). # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. # |
-- # # |
-- # Redistribution and use in source and binary forms, with or without modification, are # |
-- # permitted provided that the following conditions are met: # |
-- # # |
-- # 1. Redistributions of source code must retain the above copyright notice, this list of # |
-- # conditions and the following disclaimer. # |
-- # # |
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
-- # conditions and the following disclaimer in the documentation and/or other materials # |
-- # provided with the distribution. # |
-- # # |
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
-- # endorse or promote products derived from this software without specific prior written # |
-- # permission. # |
-- # # |
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
-- # OF THE POSSIBILITY OF SUCH DAMAGE. # |
-- # ********************************************************************************************* # |
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # |
-- ################################################################################################# |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
library neorv32; |
use neorv32.neorv32_package.all; |
|
entity neorv32_neoled is |
port ( |
-- host access -- |
clk_i : in std_ulogic; -- global clock line |
addr_i : in std_ulogic_vector(31 downto 0); -- address |
rden_i : in std_ulogic; -- read enable |
wren_i : in std_ulogic; -- write enable |
data_i : in std_ulogic_vector(31 downto 0); -- data in |
data_o : out std_ulogic_vector(31 downto 0); -- data out |
ack_o : out std_ulogic; -- transfer acknowledge |
-- clock generator -- |
clkgen_en_o : out std_ulogic; -- enable clock generator |
clkgen_i : in std_ulogic_vector(07 downto 0); |
-- interrupt -- |
irq_o : out std_ulogic; -- interrupt request |
-- NEOLED output -- |
neoled_o : out std_ulogic -- serial async data line |
); |
end neorv32_neoled; |
|
architecture neorv32_neoled_rtl of neorv32_neoled is |
|
-- TX buffer size configuration -- |
constant tx_buffer_entries_c : natural := 4; -- number of entries in TX buffer, has to be a power of two, min=0 |
|
-- IO space: module base address -- |
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit |
constant lo_abb_c : natural := index_size_f(neoled_size_c); -- low address boundary bit |
|
-- access control -- |
signal acc_en : std_ulogic; -- module access enable |
signal addr : std_ulogic_vector(31 downto 0); -- access address |
signal wren : std_ulogic; -- word write enable |
signal rden : std_ulogic; -- read enable |
|
-- Control register bits -- |
constant ctrl_enable_c : natural := 0; -- r/w: module enable |
constant ctrl_mode_c : natural := 1; -- r/w: 0 = 24-bit RGB mode, 1 = 32-bit RGBW mode |
constant ctrl_bscon_c : natural := 2; -- r/w: buffer status configuration -> busy_flag/IRQ config |
constant ctrl_clksel0_c : natural := 3; -- r/w: prescaler select bit 0 |
constant ctrl_clksel1_c : natural := 4; -- r/w: prescaler select bit 1 |
constant ctrl_clksel2_c : natural := 5; -- r/w: prescaler select bit 2 |
-- |
constant ctrl_bufs_0_c : natural := 6; -- r/-: log2(tx_buffer_entries_c) bit 0 |
constant ctrl_bufs_1_c : natural := 7; -- r/-: log2(tx_buffer_entries_c) bit 1 |
constant ctrl_bufs_2_c : natural := 8; -- r/-: log2(tx_buffer_entries_c) bit 2 |
constant ctrl_bufs_3_c : natural := 9; -- r/-: log2(tx_buffer_entries_c) bit 3 |
-- |
constant ctrl_t_tot_0_c : natural := 10; -- r/w: pulse-clock ticks per total period bit 0 |
constant ctrl_t_tot_1_c : natural := 11; -- r/w: pulse-clock ticks per total period bit 1 |
constant ctrl_t_tot_2_c : natural := 12; -- r/w: pulse-clock ticks per total period bit 2 |
constant ctrl_t_tot_3_c : natural := 13; -- r/w: pulse-clock ticks per total period bit 3 |
constant ctrl_t_tot_4_c : natural := 14; -- r/w: pulse-clock ticks per total period bit 4 |
-- |
constant ctrl_t_0h_0_c : natural := 15; -- r/w: pulse-clock ticks per ZERO high-time bit 0 |
constant ctrl_t_0h_1_c : natural := 16; -- r/w: pulse-clock ticks per ZERO high-time bit 1 |
constant ctrl_t_0h_2_c : natural := 17; -- r/w: pulse-clock ticks per ZERO high-time bit 2 |
constant ctrl_t_0h_3_c : natural := 18; -- r/w: pulse-clock ticks per ZERO high-time bit 3 |
constant ctrl_t_0h_4_c : natural := 19; -- r/w: pulse-clock ticks per ZERO high-time bit 4 |
-- |
constant ctrl_t_1h_0_c : natural := 20; -- r/w: pulse-clock ticks per ONE high-time bit 0 |
constant ctrl_t_1h_1_c : natural := 21; -- r/w: pulse-clock ticks per ONE high-time bit 1 |
constant ctrl_t_1h_2_c : natural := 22; -- r/w: pulse-clock ticks per ONE high-time bit 2 |
constant ctrl_t_1h_3_c : natural := 23; -- r/w: pulse-clock ticks per ONE high-time bit 3 |
constant ctrl_t_1h_4_c : natural := 24; -- r/w: pulse-clock ticks per ONE high-time bit 4 |
-- |
constant ctrl_tx_status_c : natural := 30; -- r/-: serial TX engine busy when set |
constant ctrl_busy_c : natural := 31; -- r/-: busy / buffer status flag (configured via ctrl_bscon_c) |
|
-- control register -- |
type ctrl_t is record |
enable : std_ulogic; |
bscon : std_ulogic; -- buffer/busy status flag configuration |
mode : std_ulogic; |
clk_prsc : std_ulogic_vector(2 downto 0); |
ready : std_ulogic; -- buffer ready to accept new data |
-- pulse config -- |
t_total : std_ulogic_vector(4 downto 0); |
t0_high : std_ulogic_vector(4 downto 0); |
t1_high : std_ulogic_vector(4 downto 0); |
end record; |
signal ctrl : ctrl_t; |
|
-- transmission buffer -- |
type tx_fifo_t is array (0 to tx_buffer_entries_c-1) of std_ulogic_vector(31+1 downto 0); |
type tx_buffer_t is record |
we : std_ulogic; -- write enable |
re : std_ulogic; -- read enable |
wdata : std_ulogic_vector(31 downto 0); -- write data (excluding excluding) |
rdata : std_ulogic_vector(31+1 downto 0); -- read data (including mode) |
-- |
w_pnt : std_ulogic_vector(index_size_f(tx_buffer_entries_c) downto 0); -- write pointer |
r_pnt : std_ulogic_vector(index_size_f(tx_buffer_entries_c) downto 0); -- read pointer |
match : std_ulogic; |
empty : std_ulogic; |
empty_ff : std_ulogic; |
full : std_ulogic; |
avail : std_ulogic; -- data available? |
free : std_ulogic; -- free entry available? |
free_ff : std_ulogic; |
-- |
data : tx_fifo_t; -- fifo memory |
end record; |
signal tx_buffer : tx_buffer_t; |
|
-- serial transmission engine -- |
type serial_state_t is (S_IDLE, S_INIT, S_GETBIT, S_PULSE); |
type serial_t is record |
-- state control -- |
state : serial_state_t; |
mode : std_ulogic; |
busy : std_ulogic; |
bit_cnt : std_ulogic_vector(5 downto 0); |
-- shift register -- |
sreg : std_ulogic_vector(31 downto 0); |
next_bit : std_ulogic; -- next bit to send |
-- pulse generator -- |
pulse_clk : std_ulogic; -- pulse cycle "clock" |
pulse_cnt : std_ulogic_vector(4 downto 0); |
t_high : std_ulogic_vector(4 downto 0); |
output : std_ulogic; |
end record; |
signal serial : serial_t; |
|
begin |
|
-- Sanity Checks -------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
assert not ((is_power_of_two_f(tx_buffer_entries_c) = false) or (tx_buffer_entries_c > 32768)) report "NEORV32 PROCESSOR CONFIG ERROR! Invalid <IO.NEOPIX> buffer size configuration!" severity error; |
|
|
-- Access Control ------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = neoled_base_c(hi_abb_c downto lo_abb_c)) else '0'; |
addr <= neoled_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned |
wren <= acc_en and wren_i; |
rden <= acc_en and rden_i; |
|
|
-- Read/Write Access ---------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
rw_access: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- access acknowledge -- |
ack_o <= wren or rden; |
|
-- write access -- |
tx_buffer.we <= '0'; |
if (wren = '1') then |
-- control register -- |
if (addr = neoled_ctrl_addr_c) then |
ctrl.enable <= data_i(ctrl_enable_c); |
ctrl.mode <= data_i(ctrl_mode_c); |
ctrl.bscon <= data_i(ctrl_bscon_c); |
ctrl.clk_prsc <= data_i(ctrl_clksel2_c downto ctrl_clksel0_c); |
ctrl.t_total <= data_i(ctrl_t_tot_4_c downto ctrl_t_tot_0_c); |
ctrl.t0_high <= data_i(ctrl_t_0h_4_c downto ctrl_t_0h_0_c); |
ctrl.t1_high <= data_i(ctrl_t_1h_4_c downto ctrl_t_1h_0_c); |
end if; |
-- tx data register (FIFO) -- |
if (addr = neoled_data_addr_c) then |
tx_buffer.wdata <= data_i; |
tx_buffer.we <= tx_buffer.free; -- only write new data if there is at least one free entry left |
end if; |
end if; |
|
-- read access: control register -- |
data_o <= (others => '0'); |
if (rden = '1') and (addr = neoled_ctrl_addr_c) then |
data_o(ctrl_enable_c) <= ctrl.enable; |
data_o(ctrl_mode_c) <= ctrl.mode; |
data_o(ctrl_bscon_c) <= ctrl.bscon; |
data_o(ctrl_clksel2_c downto ctrl_clksel0_c) <= ctrl.clk_prsc; |
data_o(ctrl_bufs_3_c downto ctrl_bufs_0_c) <= std_ulogic_vector(to_unsigned(index_size_f(tx_buffer_entries_c), 4)); |
data_o(ctrl_t_tot_4_c downto ctrl_t_tot_0_c) <= ctrl.t_total; |
data_o(ctrl_t_0h_4_c downto ctrl_t_0h_0_c) <= ctrl.t0_high; |
data_o(ctrl_t_1h_4_c downto ctrl_t_1h_0_c) <= ctrl.t1_high; |
data_o(ctrl_tx_status_c) <= serial.busy; |
data_o(ctrl_busy_c) <= not ctrl.ready; |
end if; |
end if; |
end process rw_access; |
|
-- enable external clock generator -- |
clkgen_en_o <= ctrl.enable; |
|
|
-- TX Buffer (FIFO) ----------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
instr_prefetch_buffer: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- write port -- |
if (ctrl.enable = '0') then |
tx_buffer.w_pnt <= (others => '0'); |
elsif (tx_buffer.we = '1') then |
tx_buffer.w_pnt <= std_ulogic_vector(unsigned(tx_buffer.w_pnt) + 1); |
end if; |
if (tx_buffer.we = '1') then -- write data |
tx_buffer.data(to_integer(unsigned(tx_buffer.w_pnt(tx_buffer.w_pnt'left-1 downto 0)))) <= ctrl.mode & tx_buffer.wdata; |
end if; |
-- read port -- |
if (ctrl.enable = '0') then |
tx_buffer.r_pnt <= (others => '0'); |
elsif (tx_buffer.re = '1') then |
tx_buffer.r_pnt <= std_ulogic_vector(unsigned(tx_buffer.r_pnt) + 1); |
end if; |
tx_buffer.rdata <= tx_buffer.data(to_integer(unsigned(tx_buffer.r_pnt(tx_buffer.r_pnt'left-1 downto 0)))); -- sync read |
-- status buffer -- |
tx_buffer.empty_ff <= tx_buffer.empty; |
tx_buffer.free_ff <= tx_buffer.free; |
end if; |
end process instr_prefetch_buffer; |
|
-- status -- |
tx_buffer.match <= '1' when (tx_buffer.r_pnt(tx_buffer.r_pnt'left-1 downto 0) = tx_buffer.w_pnt(tx_buffer.w_pnt'left-1 downto 0)) else '0'; |
tx_buffer.full <= '1' when (tx_buffer.r_pnt(tx_buffer.r_pnt'left) /= tx_buffer.w_pnt(tx_buffer.w_pnt'left)) and (tx_buffer.match = '1') else '0'; |
tx_buffer.empty <= '1' when (tx_buffer.r_pnt(tx_buffer.r_pnt'left) = tx_buffer.w_pnt(tx_buffer.w_pnt'left)) and (tx_buffer.match = '1') else '0'; |
tx_buffer.free <= not tx_buffer.full; |
tx_buffer.avail <= not tx_buffer.empty; |
|
|
-- Buffer Status Flag and IRQ Generator --------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- ctrl.bscon = 0: clear buffer/busy status flag and send IRQ if -> there is at least one free entry in buffer |
-- ctrl.bscon = 1: clear buffer/busy status flag and send IRQ if -> the complete buffer is empty |
irq_generator: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if (ctrl.enable = '1') then |
if (ctrl.bscon = '0') then -- one entry is becoming free |
irq_o <= (not tx_buffer.free_ff) and tx_buffer.free; |
else -- buffer is becoming empty |
irq_o <= (not tx_buffer.empty_ff) and tx_buffer.empty; |
end if; |
else |
irq_o <= '0'; |
end if; |
end if; |
end process irq_generator; |
|
-- ready flag -- |
ctrl.ready <= tx_buffer.free when (ctrl.bscon = '0') else tx_buffer.empty; |
|
|
-- Serial TX Engine ----------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
serial_engine: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- defaults -- |
serial.pulse_clk <= clkgen_i(to_integer(unsigned(ctrl.clk_prsc))); |
|
-- disabled -- |
if (ctrl.enable = '0') then -- disabled |
serial.output <= '0'; |
serial.state <= S_IDLE; |
else |
case serial.state is |
|
when S_IDLE => -- waiting for new TX data |
-- ------------------------------------------------------------ |
serial.output <= '0'; |
serial.pulse_cnt <= (others => '0'); |
if (tx_buffer.avail = '1') then |
serial.state <= S_INIT; |
end if; |
|
when S_INIT => -- initialize TX shift engine |
-- ------------------------------------------------------------ |
if (tx_buffer.rdata(32) = '0') then -- mode = "RGB" |
serial.mode <= '0'; |
serial.bit_cnt <= "011000"; -- total number of bits to send: 3x8=24 |
else -- mode = "RGBW" |
serial.mode <= '1'; |
serial.bit_cnt <= "100000"; -- total number of bits to send: 4x8=32 |
end if; |
serial.sreg <= tx_buffer.rdata(31 downto 00); |
serial.state <= S_GETBIT; |
|
when S_GETBIT => -- get next TX bit |
-- ------------------------------------------------------------ |
serial.sreg <= serial.sreg(serial.sreg'left-1 downto 0) & '0'; -- shift left by one position (MSB-first) |
serial.bit_cnt <= std_ulogic_vector(unsigned(serial.bit_cnt) - 1); |
serial.pulse_cnt <= (others => '0'); |
if (serial.bit_cnt = "000000") then -- all done? |
serial.state <= S_IDLE; |
else -- check current data MSB |
if (serial.next_bit = '0') then -- send zero-bit |
serial.t_high <= ctrl.t0_high; |
else -- send one-bit |
serial.t_high <= ctrl.t1_high; |
end if; |
serial.state <= S_PULSE; -- transmit single pulse |
serial.output <= '1'; |
end if; |
|
when S_PULSE => -- send pulse with specific duty cycle |
-- ------------------------------------------------------------ |
-- total pulse length = ctrl.t_total |
-- pulse high time = serial.t_high |
if (serial.pulse_clk = '1') then |
serial.pulse_cnt <= std_ulogic_vector(unsigned(serial.pulse_cnt) + 1); |
-- T_high reached? -- |
if (serial.pulse_cnt = serial.t_high) then |
serial.output <= '0'; |
end if; |
-- T_total reached? -- |
if (serial.pulse_cnt = ctrl.t_total) then |
serial.state <= S_GETBIT; -- get next bit to send |
end if; |
end if; |
|
when others => -- undefined |
-- ------------------------------------------------------------ |
serial.state <= S_IDLE; |
|
end case; |
end if; |
-- serial data output -- |
neoled_o <= serial.output; -- IOB.FF |
end if; |
end process serial_engine; |
|
-- SREG's TX data: bit 23 for RGB mode (24-bit), bit 31 for RGBW mode (32-bit) -- |
serial.next_bit <= serial.sreg(23) when (serial.mode = '0') else serial.sreg(31); |
|
-- get new TX data -- |
tx_buffer.re <= '1' when (serial.state = S_IDLE) and (tx_buffer.avail = '1') else '0'; |
|
-- TX engine status -- |
serial.busy <= '0' when (serial.state = S_IDLE) or (ctrl.enable = '0') else '1'; |
|
|
end neorv32_neoled_rtl; |
/neorv32/trunk/rtl/core/neorv32_package.vhd
60,7 → 60,7
-- Architecture Constants (do not modify!) ------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
constant data_width_c : natural := 32; -- native data path width - do not change! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01050200"; -- no touchy! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01050204"; -- no touchy! |
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED! |
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off! |
constant rf_r0_is_reg_c : boolean := true; -- reg_file.r0 is a *physical register* that has to be initialized to zero by the CPU HW |
203,9 → 203,11
constant uart1_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD0"; |
constant uart1_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD4"; |
|
-- reserved -- |
--constant reserved_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD8"; -- base address |
--constant reserved_size_c : natural := 2*4; -- module's address space in bytes |
-- Smart LED (WS2811/WS2812) Interface (NEOLED) -- |
constant neoled_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD8"; -- base address |
constant neoled_size_c : natural := 2*4; -- module's address space in bytes |
constant neoled_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD8"; |
constant neoled_data_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFDC"; |
|
-- System Information Memory (SYSINFO) -- |
constant sysinfo_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFE0"; -- base address |
252,46 → 254,48
constant ctrl_bus_if_c : natural := 33; -- instruction fetch request |
constant ctrl_bus_mo_we_c : natural := 34; -- memory address and data output register write enable |
constant ctrl_bus_mi_we_c : natural := 35; -- memory data input register write enable |
constant ctrl_bus_unsigned_c : natural := 36; -- is unsigned load |
constant ctrl_bus_ierr_ack_c : natural := 37; -- acknowledge instruction fetch bus exceptions |
constant ctrl_bus_derr_ack_c : natural := 38; -- acknowledge data access bus exceptions |
constant ctrl_bus_fence_c : natural := 39; -- executed fence operation |
constant ctrl_bus_fencei_c : natural := 40; -- executed fencei operation |
constant ctrl_bus_lock_c : natural := 41; -- locked/exclusive bus access |
constant ctrl_bus_wd_sel_c : natural := 36; -- memory write-data source select (0=reg_file, 1=co-proc.) |
constant ctrl_bus_unsigned_c : natural := 37; -- is unsigned load |
constant ctrl_bus_ierr_ack_c : natural := 38; -- acknowledge instruction fetch bus exceptions |
constant ctrl_bus_derr_ack_c : natural := 39; -- acknowledge data access bus exceptions |
constant ctrl_bus_fence_c : natural := 40; -- executed fence operation |
constant ctrl_bus_fencei_c : natural := 41; -- executed fencei operation |
constant ctrl_bus_lock_c : natural := 42; -- locked/exclusive bus access |
-- co-processors -- |
constant ctrl_cp_id_lsb_c : natural := 42; -- cp select ID lsb |
constant ctrl_cp_id_hsb_c : natural := 43; -- cp select ID hsb |
constant ctrl_cp_id_msb_c : natural := 44; -- cp select ID msb |
constant ctrl_cp_id_lsb_c : natural := 43; -- cp select ID lsb |
constant ctrl_cp_id_hsb_c : natural := 44; -- cp select ID hsb |
constant ctrl_cp_id_msb_c : natural := 45; -- cp select ID msb |
constant ctrl_cp_fpu_mem_we_c : natural := 46; -- fpu-cp memory-data write enable |
-- current privilege level -- |
constant ctrl_priv_lvl_lsb_c : natural := 45; -- privilege level lsb |
constant ctrl_priv_lvl_msb_c : natural := 46; -- privilege level msb |
constant ctrl_priv_lvl_lsb_c : natural := 47; -- privilege level lsb |
constant ctrl_priv_lvl_msb_c : natural := 48; -- privilege level msb |
-- instruction's control blocks (used by cpu co-processors) -- |
constant ctrl_ir_funct3_0_c : natural := 47; -- funct3 bit 0 |
constant ctrl_ir_funct3_1_c : natural := 48; -- funct3 bit 1 |
constant ctrl_ir_funct3_2_c : natural := 49; -- funct3 bit 2 |
constant ctrl_ir_funct12_0_c : natural := 50; -- funct12 bit 0 |
constant ctrl_ir_funct12_1_c : natural := 51; -- funct12 bit 1 |
constant ctrl_ir_funct12_2_c : natural := 52; -- funct12 bit 2 |
constant ctrl_ir_funct12_3_c : natural := 53; -- funct12 bit 3 |
constant ctrl_ir_funct12_4_c : natural := 54; -- funct12 bit 4 |
constant ctrl_ir_funct12_5_c : natural := 55; -- funct12 bit 5 |
constant ctrl_ir_funct12_6_c : natural := 56; -- funct12 bit 6 |
constant ctrl_ir_funct12_7_c : natural := 57; -- funct12 bit 7 |
constant ctrl_ir_funct12_8_c : natural := 58; -- funct12 bit 8 |
constant ctrl_ir_funct12_9_c : natural := 59; -- funct12 bit 9 |
constant ctrl_ir_funct12_10_c : natural := 60; -- funct12 bit 10 |
constant ctrl_ir_funct12_11_c : natural := 61; -- funct12 bit 11 |
constant ctrl_ir_opcode7_0_c : natural := 62; -- opcode7 bit 0 |
constant ctrl_ir_opcode7_1_c : natural := 63; -- opcode7 bit 1 |
constant ctrl_ir_opcode7_2_c : natural := 64; -- opcode7 bit 2 |
constant ctrl_ir_opcode7_3_c : natural := 65; -- opcode7 bit 3 |
constant ctrl_ir_opcode7_4_c : natural := 66; -- opcode7 bit 4 |
constant ctrl_ir_opcode7_5_c : natural := 67; -- opcode7 bit 5 |
constant ctrl_ir_opcode7_6_c : natural := 68; -- opcode7 bit 6 |
constant ctrl_ir_funct3_0_c : natural := 49; -- funct3 bit 0 |
constant ctrl_ir_funct3_1_c : natural := 50; -- funct3 bit 1 |
constant ctrl_ir_funct3_2_c : natural := 51; -- funct3 bit 2 |
constant ctrl_ir_funct12_0_c : natural := 52; -- funct12 bit 0 |
constant ctrl_ir_funct12_1_c : natural := 53; -- funct12 bit 1 |
constant ctrl_ir_funct12_2_c : natural := 54; -- funct12 bit 2 |
constant ctrl_ir_funct12_3_c : natural := 55; -- funct12 bit 3 |
constant ctrl_ir_funct12_4_c : natural := 56; -- funct12 bit 4 |
constant ctrl_ir_funct12_5_c : natural := 57; -- funct12 bit 5 |
constant ctrl_ir_funct12_6_c : natural := 58; -- funct12 bit 6 |
constant ctrl_ir_funct12_7_c : natural := 59; -- funct12 bit 7 |
constant ctrl_ir_funct12_8_c : natural := 60; -- funct12 bit 8 |
constant ctrl_ir_funct12_9_c : natural := 61; -- funct12 bit 9 |
constant ctrl_ir_funct12_10_c : natural := 62; -- funct12 bit 10 |
constant ctrl_ir_funct12_11_c : natural := 63; -- funct12 bit 11 |
constant ctrl_ir_opcode7_0_c : natural := 64; -- opcode7 bit 0 |
constant ctrl_ir_opcode7_1_c : natural := 65; -- opcode7 bit 1 |
constant ctrl_ir_opcode7_2_c : natural := 66; -- opcode7 bit 2 |
constant ctrl_ir_opcode7_3_c : natural := 67; -- opcode7 bit 3 |
constant ctrl_ir_opcode7_4_c : natural := 68; -- opcode7 bit 4 |
constant ctrl_ir_opcode7_5_c : natural := 69; -- opcode7 bit 5 |
constant ctrl_ir_opcode7_6_c : natural := 70; -- opcode7 bit 6 |
-- CPU status -- |
constant ctrl_sleep_c : natural := 69; -- set when CPU is in sleep mode |
constant ctrl_sleep_c : natural := 71; -- set when CPU is in sleep mode |
-- control bus size -- |
constant ctrl_width_c : natural := 70; -- control bus size |
constant ctrl_width_c : natural := 72; -- control bus size |
|
-- Comparator Bus ------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
340,8 → 344,13
-- system/csr -- |
constant opcode_fence_c : std_ulogic_vector(6 downto 0) := "0001111"; -- fence / fence.i |
constant opcode_syscsr_c : std_ulogic_vector(6 downto 0) := "1110011"; -- system/csr access (type via funct3) |
-- atomic operations (A) -- |
-- atomic memory access (A) -- |
constant opcode_atomic_c : std_ulogic_vector(6 downto 0) := "0101111"; -- atomic operations (A extension) |
-- floating point operations (F/D/H/Q) -- |
constant opcode_flw_c : std_ulogic_vector(6 downto 0) := "0000111"; -- load word |
constant opcode_fsw_c : std_ulogic_vector(6 downto 0) := "0100111"; -- store word |
constant opcode_fop_c : std_ulogic_vector(6 downto 0) := "1010011"; -- dual/single opearand operation |
constant opcode_fmac_c : std_ulogic_vector(6 downto 0) := "100--11"; -- fused multiply-add (three operands) |
|
-- RISC-V Funct3 -------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
396,14 → 405,28
constant funct5_a_lr_c : std_ulogic_vector(4 downto 0) := "00010"; -- LR |
constant funct5_a_sc_c : std_ulogic_vector(4 downto 0) := "00011"; -- SC |
|
-- RISC-V Floating-Point Formats ---------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
constant float_single_c : std_ulogic_vector(1 downto 0) := "00"; -- single-precisions (32-bit) |
constant float_double_c : std_ulogic_vector(1 downto 0) := "01"; -- double-precisions (64-bit) |
constant float_half_c : std_ulogic_vector(1 downto 0) := "10"; -- half-precisions (16-bit) |
constant float_quad_c : std_ulogic_vector(1 downto 0) := "11"; -- quad-precisions (64-bit) |
|
-- RISC-V CSR Addresses ------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- read/write CSRs -- |
constant csr_class_float_c : std_ulogic_vector(07 downto 0) := x"00"; -- floating point |
constant csr_fflags_c : std_ulogic_vector(11 downto 0) := x"001"; |
constant csr_frm_c : std_ulogic_vector(11 downto 0) := x"002"; |
constant csr_fcsr_c : std_ulogic_vector(11 downto 0) := x"003"; |
-- |
constant csr_setup_c : std_ulogic_vector(07 downto 0) := x"30"; -- trap setup |
constant csr_mstatus_c : std_ulogic_vector(11 downto 0) := x"300"; |
constant csr_misa_c : std_ulogic_vector(11 downto 0) := x"301"; |
constant csr_mie_c : std_ulogic_vector(11 downto 0) := x"304"; |
constant csr_mtvec_c : std_ulogic_vector(11 downto 0) := x"305"; |
constant csr_mcounteren_c : std_ulogic_vector(11 downto 0) := x"306"; |
-- |
constant csr_mstatush_c : std_ulogic_vector(11 downto 0) := x"310"; |
-- |
constant csr_mcountinhibit_c : std_ulogic_vector(11 downto 0) := x"320"; |
438,6 → 461,7
constant csr_mhpmevent30_c : std_ulogic_vector(11 downto 0) := x"33e"; |
constant csr_mhpmevent31_c : std_ulogic_vector(11 downto 0) := x"33f"; |
-- |
constant csr_class_trap_c : std_ulogic_vector(07 downto 0) := x"34"; -- machine trap handling |
constant csr_mscratch_c : std_ulogic_vector(11 downto 0) := x"340"; |
constant csr_mepc_c : std_ulogic_vector(11 downto 0) := x"341"; |
constant csr_mcause_c : std_ulogic_vector(11 downto 0) := x"342"; |
444,6 → 468,7
constant csr_mtval_c : std_ulogic_vector(11 downto 0) := x"343"; |
constant csr_mip_c : std_ulogic_vector(11 downto 0) := x"344"; |
-- |
constant csr_class_pmpcfg_c : std_ulogic_vector(07 downto 0) := x"3a"; -- pmp configuration |
constant csr_pmpcfg0_c : std_ulogic_vector(11 downto 0) := x"3a0"; |
constant csr_pmpcfg1_c : std_ulogic_vector(11 downto 0) := x"3a1"; |
constant csr_pmpcfg2_c : std_ulogic_vector(11 downto 0) := x"3a2"; |
675,10 → 700,10
constant cp_sel_atomic_c : std_ulogic_vector(2 downto 0) := "001"; -- atomic operations; success/failure evaluation ('A' extension) |
constant cp_sel_bitmanip_c : std_ulogic_vector(2 downto 0) := "010"; -- bit manipulation ('B' extension) |
constant cp_sel_csr_rd_c : std_ulogic_vector(2 downto 0) := "011"; -- CSR read access ('Zicsr' extension) |
--constant cp_reserved_c : std_ulogic_vector(2 downto 0) := "100"; -- reserved |
--constant cp_reserved_c : std_ulogic_vector(2 downto 0) := "101"; -- reserved |
--constant cp_reserved_c : std_ulogic_vector(2 downto 0) := "110"; -- reserved |
--constant cp_reserved_c : std_ulogic_vector(2 downto 0) := "111"; -- reserved |
constant cp_sel_fpu_c : std_ulogic_vector(2 downto 0) := "100"; -- loating-point unit ('F' extension) |
--constant cp_sel_reserved_c : std_ulogic_vector(2 downto 0) := "101"; -- reserved |
--constant cp_sel_reserved_c : std_ulogic_vector(2 downto 0) := "110"; -- reserved |
--constant cp_sel_reserved_c : std_ulogic_vector(2 downto 0) := "111"; -- reserved |
|
-- ALU Function Codes --------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
857,8 → 882,11
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)? |
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic |
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)? |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic |
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits |
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
); |
port ( |
-- Global control -- |
903,10 → 931,12
-- PWM (available if IO_PWM_EN = true) -- |
pwm_o : out std_ulogic_vector(03 downto 0); -- pwm channels |
-- Custom Functions Subsystem IO -- |
cfs_in_i : in std_ulogic_vector(31 downto 0) := (others => '0'); -- custom CSF inputs |
cfs_out_o : out std_ulogic_vector(31 downto 0); -- custom CSF outputs |
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0); -- custom CFS inputs conduit |
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom CFS outputs conduit |
-- NCO output (available if IO_NCO_EN = true) -- |
nco_o : out std_ulogic_vector(02 downto 0); -- numerically-controlled oscillator channels |
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- |
neoled_o : out std_ulogic; -- async serial data line |
-- system time input from external MTIME (available if IO_MTIME_EN = false) -- |
mtime_i : in std_ulogic_vector(63 downto 0) := (others => '0'); -- current system time |
-- Interrupts -- |
930,6 → 960,7
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions? |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_F : boolean := false; -- implement 32-bit floating-point extension? |
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system? |
938,7 → 969,7
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0 -- number of implemented HPM counters (0..29) |
998,12 → 1029,13
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions? |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_F : boolean := false; -- implement 32-bit floating-point extension? |
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.? |
-- Physical memory protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0 -- number of implemented HPM counters (0..29) |
1021,12 → 1053,15
instr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- instruction |
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status |
alu_add_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU address result |
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1 |
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1 |
-- data output -- |
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate |
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch |
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction) |
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data |
-- FPU interface -- |
fpu_rm_o : out std_ulogic_vector(02 downto 0); -- rounding mode |
fpu_flags_i : in std_ulogic_vector(04 downto 0); -- exception flags |
-- interrupts (risc-v compliant) -- |
msw_irq_i : in std_ulogic; -- machine software interrupt |
mext_irq_i : in std_ulogic; -- machine external interrupt |
1139,6 → 1174,27
); |
end component; |
|
-- Component: CPU Co-Processor 32-bit FPU ('F' extension) --------------------------------- |
-- ------------------------------------------------------------------------------------------- |
component neorv32_cpu_cp_fpu |
port ( |
-- global control -- |
clk_i : in std_ulogic; -- global clock, rising edge |
rstn_i : in std_ulogic; -- global reset, low-active, async |
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus |
start_i : in std_ulogic; -- trigger operation |
-- data input -- |
frm_i : in std_ulogic_vector(2 downto 0); -- rounding mode |
reg_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source |
mem_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory read-data |
-- result and status -- |
fflags_o : out std_ulogic_vector(4 downto 0); -- exception flags |
mem_o : out std_ulogic_vector(data_width_c-1 downto 0); -- memory write-data |
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operation result |
valid_o : out std_ulogic -- data output valid |
); |
end component; |
|
-- Component: CPU Bus Interface ----------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
component neorv32_cpu_bus |
1580,7 → 1636,9
-- ------------------------------------------------------------------------------------------- |
component neorv32_cfs |
generic ( |
CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000" -- custom CFS configuration generic |
CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic |
CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits |
CFS_OUT_SIZE : positive := 32 -- size of CFS output conduit in bits |
); |
port ( |
-- host access -- |
1601,8 → 1659,8
irq_o : out std_ulogic; -- interrupt request |
irq_ack_i : in std_ulogic; -- interrupt acknowledge |
-- custom io (conduit) -- |
cfs_in_i : in std_ulogic_vector(31 downto 0); -- custom inputs |
cfs_out_o : out std_ulogic_vector(31 downto 0) -- custom outputs |
cfs_in_i : in std_ulogic_vector(CFS_IN_SIZE-1 downto 0); -- custom inputs |
cfs_out_o : out std_ulogic_vector(CFS_OUT_SIZE-1 downto 0) -- custom outputs |
); |
end component; |
|
1626,6 → 1684,28
); |
end component; |
|
-- Component: Smart LED (WS2811/WS2812) Interface (NEOLED) -------------------------------- |
-- ------------------------------------------------------------------------------------------- |
component neorv32_neoled |
port ( |
-- host access -- |
clk_i : in std_ulogic; -- global clock line |
addr_i : in std_ulogic_vector(31 downto 0); -- address |
rden_i : in std_ulogic; -- read enable |
wren_i : in std_ulogic; -- write enable |
data_i : in std_ulogic_vector(31 downto 0); -- data in |
data_o : out std_ulogic_vector(31 downto 0); -- data out |
ack_o : out std_ulogic; -- transfer acknowledge |
-- clock generator -- |
clkgen_en_o : out std_ulogic; -- enable clock generator |
clkgen_i : in std_ulogic_vector(07 downto 0); |
-- interrupt -- |
irq_o : out std_ulogic; -- interrupt request |
-- NEOLED output -- |
neoled_o : out std_ulogic -- serial async data line |
); |
end component; |
|
-- Component: System Configuration Information Memory (SYSINFO) --------------------------- |
-- ------------------------------------------------------------------------------------------- |
component neorv32_sysinfo |
1659,7 → 1739,8
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_EN : boolean := true; -- implement true random number generator (TRNG)? |
IO_CFS_EN : boolean := true; -- implement custom functions subsystem (CFS)? |
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)? |
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
); |
port ( |
-- host access -- |
/neorv32/trunk/rtl/core/neorv32_sysinfo.vhd
73,7 → 73,8
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_EN : boolean := true; -- implement true random number generator (TRNG)? |
IO_CFS_EN : boolean := true; -- implement custom functions subsystem (CFS)? |
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)? |
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
); |
port ( |
-- host access -- |
132,19 → 133,20
-- |
sysinfo_mem(2)(15 downto 07) <= (others => '0'); -- reserved |
-- IO -- |
sysinfo_mem(2)(16) <= bool_to_ulogic_f(IO_GPIO_EN); -- general purpose input/output port unit (GPIO) implemented? |
sysinfo_mem(2)(17) <= bool_to_ulogic_f(IO_MTIME_EN); -- machine system timer (MTIME) implemented? |
sysinfo_mem(2)(18) <= bool_to_ulogic_f(IO_UART0_EN); -- primary universal asynchronous receiver/transmitter (UART0) implemented? |
sysinfo_mem(2)(19) <= bool_to_ulogic_f(IO_SPI_EN); -- serial peripheral interface (SPI) implemented? |
sysinfo_mem(2)(20) <= bool_to_ulogic_f(IO_TWI_EN); -- two-wire interface (TWI) implemented? |
sysinfo_mem(2)(21) <= bool_to_ulogic_f(IO_PWM_EN); -- pulse-width modulation unit (PWM) implemented? |
sysinfo_mem(2)(22) <= bool_to_ulogic_f(IO_WDT_EN); -- watch dog timer (WDT) implemented? |
sysinfo_mem(2)(23) <= bool_to_ulogic_f(IO_CFS_EN); -- custom functions subsystem (CFS) implemented? |
sysinfo_mem(2)(24) <= bool_to_ulogic_f(IO_TRNG_EN); -- true random number generator (TRNG) implemented? |
sysinfo_mem(2)(25) <= bool_to_ulogic_f(IO_NCO_EN); -- numerically-controlled oscillator (NCO) implemented? |
sysinfo_mem(2)(26) <= bool_to_ulogic_f(IO_UART1_EN); -- secondary universal asynchronous receiver/transmitter (UART1) implemented? |
sysinfo_mem(2)(16) <= bool_to_ulogic_f(IO_GPIO_EN); -- general purpose input/output port unit (GPIO) implemented? |
sysinfo_mem(2)(17) <= bool_to_ulogic_f(IO_MTIME_EN); -- machine system timer (MTIME) implemented? |
sysinfo_mem(2)(18) <= bool_to_ulogic_f(IO_UART0_EN); -- primary universal asynchronous receiver/transmitter (UART0) implemented? |
sysinfo_mem(2)(19) <= bool_to_ulogic_f(IO_SPI_EN); -- serial peripheral interface (SPI) implemented? |
sysinfo_mem(2)(20) <= bool_to_ulogic_f(IO_TWI_EN); -- two-wire interface (TWI) implemented? |
sysinfo_mem(2)(21) <= bool_to_ulogic_f(IO_PWM_EN); -- pulse-width modulation unit (PWM) implemented? |
sysinfo_mem(2)(22) <= bool_to_ulogic_f(IO_WDT_EN); -- watch dog timer (WDT) implemented? |
sysinfo_mem(2)(23) <= bool_to_ulogic_f(IO_CFS_EN); -- custom functions subsystem (CFS) implemented? |
sysinfo_mem(2)(24) <= bool_to_ulogic_f(IO_TRNG_EN); -- true random number generator (TRNG) implemented? |
sysinfo_mem(2)(25) <= bool_to_ulogic_f(IO_NCO_EN); -- numerically-controlled oscillator (NCO) implemented? |
sysinfo_mem(2)(26) <= bool_to_ulogic_f(IO_UART1_EN); -- secondary universal asynchronous receiver/transmitter (UART1) implemented? |
sysinfo_mem(2)(27) <= bool_to_ulogic_f(IO_NEOLED_EN); -- NeoPixel-compatible smart LED interface (NEOLED) implemented? |
-- |
sysinfo_mem(2)(31 downto 27) <= (others => '0'); -- reserved |
sysinfo_mem(2)(31 downto 28) <= (others => '0'); -- reserved |
|
-- SYSINFO(3): Cache configuration -- |
sysinfo_mem(3)(03 downto 00) <= std_ulogic_vector(to_unsigned(index_size_f(ICACHE_BLOCK_SIZE), 4)) when (ICACHE_EN = true) else (others => '0'); -- i-cache: log2(block_size_in_bytes) |
/neorv32/trunk/rtl/core/neorv32_top.vhd
103,8 → 103,11
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)? |
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic |
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)? |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic |
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits |
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
); |
port ( |
-- Global control -- |
158,12 → 161,15
pwm_o : out std_ulogic_vector(03 downto 0); -- pwm channels |
|
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) -- |
cfs_in_i : in std_ulogic_vector(31 downto 0) := (others => '0'); -- custom CFS inputs conduit |
cfs_out_o : out std_ulogic_vector(31 downto 0); -- custom CFS outputs conduit |
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0); -- custom CFS inputs conduit |
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom CFS outputs conduit |
|
-- NCO output (available if IO_NCO_EN = true) -- |
nco_o : out std_ulogic_vector(02 downto 0); -- numerically-controlled oscillator channels |
|
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- |
neoled_o : out std_ulogic; -- async serial data line |
|
-- system time input from external MTIME (available if IO_MTIME_EN = false) -- |
mtime_i : in std_ulogic_vector(63 downto 0) := (others => '0'); -- current system time |
|
201,16 → 207,17
signal clk_div : std_ulogic_vector(11 downto 0); |
signal clk_div_ff : std_ulogic_vector(11 downto 0); |
signal clk_gen : std_ulogic_vector(07 downto 0); |
signal clk_gen_en : std_ulogic_vector(07 downto 0); |
signal clk_gen_en : std_ulogic_vector(08 downto 0); |
-- |
signal wdt_cg_en : std_ulogic; |
signal uart0_cg_en : std_ulogic; |
signal uart1_cg_en : std_ulogic; |
signal spi_cg_en : std_ulogic; |
signal twi_cg_en : std_ulogic; |
signal pwm_cg_en : std_ulogic; |
signal cfs_cg_en : std_ulogic; |
signal nco_cg_en : std_ulogic; |
signal wdt_cg_en : std_ulogic; |
signal uart0_cg_en : std_ulogic; |
signal uart1_cg_en : std_ulogic; |
signal spi_cg_en : std_ulogic; |
signal twi_cg_en : std_ulogic; |
signal pwm_cg_en : std_ulogic; |
signal cfs_cg_en : std_ulogic; |
signal nco_cg_en : std_ulogic; |
signal neoled_cg_en : std_ulogic; |
|
-- bus interface -- |
type bus_interface_t is record |
267,6 → 274,8
signal cfs_ack : std_ulogic; |
signal nco_rdata : std_ulogic_vector(data_width_c-1 downto 0); |
signal nco_ack : std_ulogic; |
signal neoled_rdata : std_ulogic_vector(data_width_c-1 downto 0); |
signal neoled_ack : std_ulogic; |
signal sysinfo_rdata : std_ulogic_vector(data_width_c-1 downto 0); |
signal sysinfo_ack : std_ulogic; |
|
286,6 → 295,7
signal twi_irq : std_ulogic; |
signal cfs_irq : std_ulogic; |
signal cfs_irq_ack : std_ulogic; |
signal neoled_irq : std_ulogic; |
|
-- misc -- |
signal mtime_time : std_ulogic_vector(63 downto 0); -- current system time from MTIME |
364,6 → 374,7
clk_gen_en(5) <= pwm_cg_en; |
clk_gen_en(6) <= cfs_cg_en; |
clk_gen_en(7) <= nco_cg_en; |
clk_gen_en(8) <= neoled_cg_en; |
if (or_all_f(clk_gen_en) = '1') then |
clk_div <= std_ulogic_vector(unsigned(clk_div) + 1); |
end if; |
400,6 → 411,7
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit manipulation extensions? |
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension? |
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_F => false, -- implement 32-bit floating-point extension? |
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system? |
473,7 → 485,7
fast_irq(06) <= spi_irq; -- SPI transmission done |
fast_irq(07) <= twi_irq; -- TWI transmission done |
fast_irq(08) <= gpio_irq; -- GPIO pin-change |
fast_irq(09) <= '0'; -- reserved |
fast_irq(09) <= neoled_irq; -- NEOLED buffer free |
|
-- fast interrupts - platform level (for custom use) -- |
fast_irq(10) <= soc_firq_i(0); |
591,11 → 603,11
|
-- processor bus: CPU transfer data input -- |
p_bus.rdata <= (imem_rdata or dmem_rdata or bootrom_rdata) or wishbone_rdata or (gpio_rdata or mtime_rdata or uart0_rdata or uart1_rdata or |
spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or trng_rdata or cfs_rdata or nco_rdata or sysinfo_rdata); |
spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or trng_rdata or cfs_rdata or nco_rdata or neoled_rdata or sysinfo_rdata); |
|
-- processor bus: CPU transfer ACK input -- |
p_bus.ack <= (imem_ack or dmem_ack or bootrom_ack) or wishbone_ack or (gpio_ack or mtime_ack or uart0_ack or uart1_ack or |
spi_ack or twi_ack or pwm_ack or wdt_ack or trng_ack or cfs_ack or nco_ack or sysinfo_ack); |
spi_ack or twi_ack or pwm_ack or wdt_ack or trng_ack or cfs_ack or nco_ack or neoled_ack or sysinfo_ack); |
|
-- processor bus: CPU transfer data bus error input -- |
p_bus.err <= wishbone_err; |
764,7 → 776,9
if (IO_CFS_EN = true) generate |
neorv32_cfs_inst: neorv32_cfs |
generic map ( |
CFS_CONFIG => IO_CFS_CONFIG -- custom CFS configuration generic |
CFS_CONFIG => IO_CFS_CONFIG, -- custom CFS configuration generic |
CFS_IN_SIZE => IO_CFS_IN_SIZE, -- size of CFS input conduit in bits |
CFS_OUT_SIZE => IO_CFS_OUT_SIZE -- size of CFS output conduit in bits |
) |
port map ( |
-- host access -- |
1145,6 → 1159,40
end generate; |
|
|
-- Smart LED (WS2811/WS2812) Interface (NEOLED) ------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
neorv32_neoled_inst_true: |
if (IO_NEOLED_EN = true) generate |
neorv32_neoled_inst: neorv32_neoled |
port map ( |
-- host access -- |
clk_i => clk_i, -- global clock line |
addr_i => p_bus.addr, -- address |
rden_i => io_rden, -- read enable |
wren_i => io_wren, -- write enable |
data_i => p_bus.wdata, -- data in |
data_o => neoled_rdata, -- data out |
ack_o => neoled_ack, -- transfer acknowledge |
-- clock generator -- |
clkgen_en_o => neoled_cg_en, -- enable clock generator |
clkgen_i => clk_gen, |
-- interrupt -- |
irq_o => neoled_irq, -- interrupt request |
-- NEOLED output -- |
neoled_o => neoled_o -- serial async data line |
); |
end generate; |
|
neorv32_neoled_inst_false: |
if (IO_NEOLED_EN = false) generate |
neoled_rdata <= (others => '0'); |
neoled_ack <= '0'; |
neoled_cg_en <= '0'; |
neoled_irq <= '0'; |
neoled_o <= '0'; |
end generate; |
|
|
-- System Configuration Information Memory (SYSINFO) -------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
neorv32_sysinfo_inst: neorv32_sysinfo |
1178,7 → 1226,8
IO_WDT_EN => IO_WDT_EN, -- implement watch dog timer (WDT)? |
IO_TRNG_EN => IO_TRNG_EN, -- implement true random number generator (TRNG)? |
IO_CFS_EN => IO_CFS_EN, -- implement custom functions subsystem (CFS)? |
IO_NCO_EN => IO_NCO_EN -- implement numerically-controlled oscillator (NCO)? |
IO_NCO_EN => IO_NCO_EN, -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN => IO_NEOLED_EN -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
) |
port map ( |
-- host access -- |
/neorv32/trunk/rtl/top_templates/neorv32_test_setup.vhd
116,7 → 116,10
IO_TRNG_EN => false, -- implement true random number generator (TRNG)? |
IO_CFS_EN => false, -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG => x"00000000", -- custom CFS configuration generic |
IO_NCO_EN => false -- implement numerically-controlled oscillator (NCO)? |
IO_CFS_IN_SIZE => 32, -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE => 32, -- size of CFS output conduit in bits |
IO_NCO_EN => false, -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN => false -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
) |
port map ( |
-- Global control -- |
165,6 → 168,8
cfs_out_o => open, -- custom outputs |
-- NCO output (available if IO_NCO_EN = true) -- |
nco_o => open, -- numerically-controlled oscillator channels |
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- |
neoled_o => open, -- async serial data line |
-- system time input from external MTIME (available if IO_MTIME_EN = false) -- |
mtime_i => (others => '0'), -- current system time |
-- Interrupts -- |
/neorv32/trunk/rtl/top_templates/neorv32_top_axi4lite.vhd
91,8 → 91,11
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)? |
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG : std_logic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic |
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)? |
IO_CFS_CONFIG : std_logic_vector(31 downto 0); -- custom CFS configuration generic |
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits |
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
); |
port ( |
-- ------------------------------------------------------------ |
152,10 → 155,12
-- PWM (available if IO_PWM_EN = true) -- |
pwm_o : out std_logic_vector(03 downto 0); -- pwm channels |
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) -- |
cfs_in_i : in std_logic_vector(31 downto 0); -- custom inputs |
cfs_out_o : out std_logic_vector(31 downto 0); -- custom outputs |
cfs_in_i : in std_logic_vector(IO_CFS_IN_SIZE-1 downto 0); -- custom inputs |
cfs_out_o : out std_logic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom outputs |
-- NCO output (available if IO_NCO_EN = true) -- |
nco_o : out std_logic_vector(02 downto 0); -- numerically-controlled oscillator channels |
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- |
neoled_o : out std_logic; -- async serial data line |
-- Interrupts -- |
soc_firq_i : in std_logic_vector(5 downto 0) := (others => '0'); -- fast interrupt channels |
mtime_irq_i : in std_logic := '0'; -- machine timer interrupt, available if IO_MTIME_EN = false |
193,11 → 198,13
-- |
signal pwm_o_int : std_ulogic_vector(03 downto 0); |
-- |
signal cfs_in_i_int : std_ulogic_vector(31 downto 0); |
signal cfs_out_o_int : std_ulogic_vector(31 downto 0); |
signal cfs_in_i_int : std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0); |
signal cfs_out_o_int : std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); |
-- |
signal nco_o_int : std_ulogic_vector(02 downto 0); |
-- |
signal neoled_o_int : std_ulogic; |
-- |
signal soc_firq_i_int : std_ulogic_vector(05 downto 0); |
signal mtime_irq_i_int : std_ulogic; |
signal msw_irq_i_int : std_ulogic; |
289,7 → 296,10
IO_TRNG_EN => IO_TRNG_EN, -- implement true random number generator (TRNG)? |
IO_CFS_EN => IO_CFS_EN, -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG => IO_CFS_CONFIG_INT, -- custom CFS configuration generic |
IO_NCO_EN => IO_NCO_EN -- implement numerically-controlled oscillator (NCO)? |
IO_CFS_IN_SIZE => IO_CFS_IN_SIZE, -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE => IO_CFS_OUT_SIZE, -- size of CFS output conduit in bits |
IO_NCO_EN => IO_NCO_EN, -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN => IO_NEOLED_EN -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
) |
port map ( |
-- Global control -- |
338,6 → 348,8
cfs_out_o => cfs_out_o_int, -- custom outputs |
-- NCO output (available if IO_NCO_EN = true) -- |
nco_o => nco_o_int, -- numerically-controlled oscillator channels |
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- |
neoled_o =>neoled_o_int, -- async serial data line |
-- system time input from external MTIME (available if IO_MTIME_EN = false) -- |
mtime_i => (others => '0'), -- current system time |
-- Interrupts -- |
368,6 → 380,8
|
nco_o <= std_logic_vector(nco_o_int); |
|
neoled_o <= std_logic(neoled_o_int); |
|
soc_firq_i_int <= std_ulogic_vector(soc_firq_i); |
msw_irq_i_int <= std_ulogic(msw_irq_i); |
mext_irq_i_int <= std_ulogic(mext_irq_i); |
/neorv32/trunk/rtl/top_templates/neorv32_top_stdlogic.vhd
88,8 → 88,11
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)? |
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic |
IO_NCO_EN : boolean := true -- implement numerically-controlled oscillator (NCO)? |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic |
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits |
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
); |
port ( |
-- Global control -- |
134,10 → 137,12
-- PWM (available if IO_PWM_EN = true) -- |
pwm_o : out std_logic_vector(03 downto 0); -- pwm channels |
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) -- |
cfs_in_i : in std_logic_vector(31 downto 0); -- custom inputs |
cfs_out_o : out std_logic_vector(31 downto 0); -- custom outputs |
cfs_in_i : in std_logic_vector(IO_CFS_IN_SIZE-1 downto 0); -- custom inputs |
cfs_out_o : out std_logic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom outputs |
-- NCO output (available if IO_NCO_EN = true) -- |
nco_o : out std_logic_vector(02 downto 0); -- numerically-controlled oscillator channels |
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- |
neoled_o : out std_logic; -- async serial data line |
-- system time input from external MTIME (available if IO_MTIME_EN = false) -- |
mtime_i : in std_logic_vector(63 downto 0) := (others => '0'); -- current system time |
-- Interrupts -- |
192,11 → 197,13
-- |
signal pwm_o_int : std_ulogic_vector(03 downto 0); |
-- |
signal cfs_in_i_int : std_ulogic_vector(31 downto 0); |
signal cfs_out_o_int : std_ulogic_vector(31 downto 0); |
signal cfs_in_i_int : std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0); |
signal cfs_out_o_int : std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); |
-- |
signal nco_o_int : std_ulogic_vector(02 downto 0); |
-- |
signal neoled_o_int : std_ulogic; |
-- |
signal mtime_i_int : std_ulogic_vector(63 downto 0); |
-- |
signal soc_firq_i_int : std_ulogic_vector(05 downto 0); |
258,7 → 265,10
IO_TRNG_EN => IO_TRNG_EN, -- implement true random number generator (TRNG)? |
IO_CFS_EN => IO_CFS_EN, -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG => IO_CFS_CONFIG_INT, -- custom CFS configuration generic |
IO_NCO_EN => IO_NCO_EN -- implement numerically-controlled oscillator (NCO)? |
IO_CFS_IN_SIZE => IO_CFS_IN_SIZE, -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE => IO_CFS_OUT_SIZE, -- size of CFS output conduit in bits |
IO_NCO_EN => IO_NCO_EN, -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN => IO_NEOLED_EN -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
) |
port map ( |
-- Global control -- |
307,6 → 317,8
cfs_out_o => cfs_out_o_int, -- custom outputs |
-- NCO output (available if IO_NCO_EN = true) -- |
nco_o => nco_o_int, -- numerically-controlled oscillator channels |
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- |
neoled_o =>neoled_o_int, -- async serial data line |
-- system time input from external MTIME (available if IO_MTIME_EN = false) -- |
mtime_i => mtime_i_int, -- current system time |
-- Interrupts -- |
355,6 → 367,8
|
nco_o <= std_logic_vector(nco_o_int); |
|
neoled_o <= std_logic(neoled_o_int); |
|
mtime_i_int <= std_ulogic_vector(mtime_i); |
|
soc_firq_i_int <= std_ulogic_vector(soc_firq_i); |
/neorv32/trunk/sim/ghdl/ghdl_sim.sh
48,6 → 48,7
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_bus.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_control.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_cp_bitmanip.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_cp_fpu.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_cp_muldiv.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_decompressor.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_regfile.vhd |
56,6 → 57,7
ghdl -a --work=neorv32 $srcdir_core/neorv32_imem.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_mtime.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_nco.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_neoled.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_pwm.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_spi.vhd |
ghdl -a --work=neorv32 $srcdir_core/neorv32_sysinfo.vhd |
/neorv32/trunk/sim/neorv32_tb.vhd
233,7 → 233,10
IO_TRNG_EN => false, -- trng cannot be simulated |
IO_CFS_EN => true, -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG => (others => '0'), -- custom CFS configuration generic |
IO_NCO_EN => true -- implement numerically-controlled oscillator (NCO)? |
IO_CFS_IN_SIZE => 32, -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE => 32, -- size of CFS output conduit in bits |
IO_NCO_EN => true, -- implement numerically-controlled oscillator (NCO)? |
IO_NEOLED_EN => true -- implement NeoPixel-compatible smart LED interface (NEOLED)? |
) |
port map ( |
-- Global control -- |
281,7 → 284,9
cfs_in_i => (others => '0'), -- custom CFS inputs |
cfs_out_o => open, -- custom CFS outputs |
-- NCO output (available if IO_NCO_EN = true) -- |
nco_o => open, -- numerically-controlled oscillator channels |
nco_o => open, -- numerically-controlled oscillator channels |
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- |
neoled_o => open, -- async serial data line |
-- system time input from external MTIME (available if IO_MTIME_EN = false) -- |
mtime_i => (others => '0'), -- current system time |
-- Interrupts -- |
/neorv32/trunk/sw/common/crt0.S
47,7 → 47,7
.cfi_undefined ra |
|
// ********************************************************* |
// Clear register file (lower half, assume E extension) |
// Clear integer register file (lower half, assume E extension) |
// ********************************************************* |
__crt0_reg_file_clear: |
//addi x0, x0, 0 // hardwired to zero |
69,10 → 69,18
|
|
// ********************************************************* |
// Clear register file (upper half, if no E extension) |
// Initialize dummy trap handler base address |
// ********************************************************* |
__crt0_neorv32_trap_init: |
la x11, __crt0_dummy_trap_handler |
csrw mtvec, x11 // set address of first-level exception handler |
|
|
// ********************************************************* |
// Clear integer register file (upper half, if no E extension) |
// ********************************************************* |
#ifndef __riscv_32e |
// save some program space if compiling bootloader |
// DO NOT DO THIS if compiling bootloader (to save some program space) |
#ifndef make_bootloader |
addi x16, x0, 0 |
addi x17, x0, 0 |
95,6 → 103,48
|
|
// ********************************************************* |
// Clear floating-point register file (if F extension enabled) |
// ********************************************************* |
#ifdef __riscv_flen |
// DO NOT DO THIS if compiling bootloader (to save some program space) |
#ifndef make_bootloader |
fmv.s.x f0, x0 |
fmv.s.x f1, x0 |
fmv.s.x f2, x0 |
fmv.s.x f3, x0 |
fmv.s.x f4, x0 |
fmv.s.x f5, x0 |
fmv.s.x f6, x0 |
fmv.s.x f7, x0 |
fmv.s.x f8, x0 |
fmv.s.x f9, x0 |
fmv.s.x f10, x0 |
fmv.s.x f11, x0 |
fmv.s.x f12, x0 |
fmv.s.x f13, x0 |
fmv.s.x f14, x0 |
fmv.s.x f15, x0 |
fmv.s.x f16, x0 |
fmv.s.x f17, x0 |
fmv.s.x f18, x0 |
fmv.s.x f19, x0 |
fmv.s.x f20, x0 |
fmv.s.x f21, x0 |
fmv.s.x f22, x0 |
fmv.s.x f23, x0 |
fmv.s.x f24, x0 |
fmv.s.x f25, x0 |
fmv.s.x f26, x0 |
fmv.s.x f27, x0 |
fmv.s.x f28, x0 |
fmv.s.x f29, x0 |
fmv.s.x f30, x0 |
fmv.s.x f31, x0 |
#endif |
#endif |
|
|
// ********************************************************* |
// No interrupts, thanks |
// ********************************************************* |
__crt0_status_init: |
117,14 → 167,6
|
|
// ********************************************************* |
// Initialize dummy trap handler base address |
// ********************************************************* |
__crt0_neorv32_trap_init: |
la x11, __crt0_dummy_trap_handler |
csrw mtvec, x11 // set address of first-level exception handler |
|
|
// ********************************************************* |
// Reset/deactivate IO/peripheral devices |
// Devices, that are not implemented, will cause a store access fault |
// which is captured but actually ignored due to the dummy handler. |
/neorv32/trunk/sw/example/bit_manipulation/README.md
2,9 → 2,9
|
:warning: The RISC-V `B` extension is not ratified yet. Hence, it is not supported by the upstream RISC-V GCC port. |
|
:warning: The NEORV32's bit manipulation instruction only supports the `Zbb` base instructions subset yet. |
:warning: The NEORV32's bit manipulation does not support *all* instructions of the `B` extension yet. |
|
The provided test program `main.c` verifies all instructions of the `B.Zbb` extensions by checking the results against a pure-software emulation model. |
The provided test program `main.c` verifies all currently implemented instruction by checking the results against a pure-software emulation model. |
The emulation functions as well as the available **intrinsics** for the `B` extension are located in `neorv32_b_extension_intrinsics.h`. |
|
:information_source: More information regarding the RISC-V bit manipulation extension can be found in the officail GitHub repo: |
11,5 → 11,3
[github.com/riscv/riscv-bitmanip](https://github.com/riscv/riscv-bitmanip). The current specification of the bitmanipulation spec supported by the NEORV32 |
can be found in `docs/bitmanip-draft.pdf`. |
|
:information_source: Compiling the test program (`main.c`) and/or the intriniscs library using the `MARCH` `b` flag should be avoided (might add further instructions from the `B` extension |
that are not part of the `Zbb` subset). |
/neorv32/trunk/sw/example/demo_gpio_irq/main.c
106,11 → 106,10
|
|
// The pin-change interrupt of the GPIO module is connected to the |
// CPU's fast interrupt input channel 1 (= FIRQ1). |
// CPU's fast interrupt input channel 8 (= FIRQ8). |
|
// install interrupt handler for GPIO pin-change interrupt |
int install_err = 0; |
install_err += neorv32_rte_exception_install(RTE_TRAP_FIRQ_1, gpio_pin_change_irq_handler); |
int install_err = neorv32_rte_exception_install(RTE_TRAP_FIRQ_8, gpio_pin_change_irq_handler); |
|
if (install_err) { |
neorv32_uart_printf("RTE install error!\n"); |
117,9 → 116,14
return 0; |
} |
|
// activate fast interrupt channel 1 (which is GPIO_PIN_CHANGE) |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ1E); |
// activate fast interrupt channel 8 (which is GPIO_PIN_CHANGE) |
install_err = neorv32_cpu_irq_enable(CSR_MIE_FIRQ8E); |
|
if (install_err) { |
neorv32_uart_printf("IRQ enable error!\n"); |
return 0; |
} |
|
// activate GPIO pin-change irq only for input pins 0 to 7 |
neorv32_gpio_pin_change_config(0x000000ff); |
|
/neorv32/trunk/sw/example/demo_neopixel/main.c
0,0 → 1,158
// ################################################################################################# |
// # << NEORV32 - Smart LED (NeoPixel/WS2812) Hardware Interface (NEOLED) Demo Program >> # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. # |
// # # |
// # Redistribution and use in source and binary forms, with or without modification, are # |
// # permitted provided that the following conditions are met: # |
// # # |
// # 1. Redistributions of source code must retain the above copyright notice, this list of # |
// # conditions and the following disclaimer. # |
// # # |
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
// # conditions and the following disclaimer in the documentation and/or other materials # |
// # provided with the distribution. # |
// # # |
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
// # endorse or promote products derived from this software without specific prior written # |
// # permission. # |
// # # |
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
// # OF THE POSSIBILITY OF SUCH DAMAGE. # |
// # ********************************************************************************************* # |
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # |
// ################################################################################################# |
|
|
/**********************************************************************//** |
* @file demo_neopixel/main.c |
* @author Stephan Nolting |
* @brief NeoPixel (WS2812) interface demo using the processor's smart LED interface (NEOLED). |
**************************************************************************/ |
|
#include <neorv32.h> |
|
|
/**********************************************************************//** |
* @name User configuration |
**************************************************************************/ |
/**@{*/ |
/** UART BAUD rate */ |
#define BAUD_RATE 19200 |
/** Number of RGB LEDs in stripe A (24-bit data) */ |
#define NUM_LEDS_24BIT (12) |
/** Number of RGBW LEDs in stripe B (32-bit data) */ |
#define NUM_LEDS_32BIT (8) |
/**@}*/ |
|
|
/**********************************************************************//** |
* Main function |
* This demo uses two NeoPixel stripes: Stripe A is a 12-LED RGB ring (arranged as ring - NOT CONNECTED as ring), stripe B is a 8-LED RGBW stripe |
* |
* @note This program requires the NEOLED controller to be synthesized (UART0 is optional). |
* @note NeoPixel stripe connection: NEORV32.neoled_o -> Stripe A ("NUM_LEDS_24BIT" RGB-LEDs) -> Stripe B ("NUM_LEDS_32BIT" RGBW LEDs) |
* |
* @return Irrelevant. |
**************************************************************************/ |
int main() { |
|
// capture all exceptions and give debug info via UART0 |
// this is not required, but keeps us safe |
neorv32_rte_setup(); |
|
|
// init UART0 at default baud rate, no parity bits, no hw flow control |
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE); |
neorv32_uart0_printf("<<< NEORV32 NeoPixel (WS2812) hardware interface (NEOLED) demo >>>\n"); |
neorv32_uart0_printf("(c) 'NeoPixel' is a trademark of Adafruit Industries.\n"); |
|
|
// check if NEOLED unit is implemented at all, abort if not |
if (neorv32_neoled_available() == 0) { |
neorv32_uart_printf("Error! No NEOLED unit synthesized!\n"); |
return 0; |
} |
|
|
// clearify setup |
neorv32_uart0_printf("\nThis demo uses the following LED setup:\n"); |
neorv32_uart0_printf("NEORV32.neoled_o -> %u RGB-LEDs (24-bit) -> %u RGBW-LEDs (32-bit)\n\n", (uint32_t)NUM_LEDS_24BIT, (uint32_t)NUM_LEDS_32BIT); |
|
|
// use the "neorv32_neoled_setup_ws2812()" setup function here instead the raw "neorv32_neoled_setup_raw()" |
// neorv32_neoled_setup_ws2812() will configure all timing parameters according to the WS2812 specs. for the current processor clock speed |
neorv32_neoled_setup_ws2812(0); // use bscon = 0 (busy_flag clears / IRQ fires if at least one buffer entry is free) |
|
|
// check NEOLED configuration |
neorv32_uart0_printf("Checking NEOLED configuration:\n", neorv32_neoled_get_buffer_size()); |
neorv32_uart0_printf(" Hardware buffer size: %u entries\n", neorv32_neoled_get_buffer_size()); |
neorv32_uart0_printf(" Control register: 0x%x\n\n", NEOLED_CT); |
|
|
// clear all LEDs |
neorv32_uart0_printf("Clearing all LEDs...\n"); |
int i; |
for (i=0; i<(NUM_LEDS_24BIT+NUM_LEDS_32BIT); i++) { // just send a lot of zeros |
neorv32_neoled_send_polling(1, 0); // mode = 1 = 32-bit, -> send 32 zero bits in each iteration |
} |
neorv32_cpu_delay_ms(1000); |
|
|
// a simple (but fancy!) animation example |
neorv32_uart0_printf("Starting animation...\n"); |
int stripe_pos_rgb = 0, flash_position = 0, flash_direction = -1; |
int stripe_pos_rgbw = 0, circle_position = 0; |
uint32_t circle_color = 0x00000004; |
|
while (1) { |
|
// RGB LEDs: turning circle, changes color after each completed cycle |
for (stripe_pos_rgb=0; stripe_pos_rgb<NUM_LEDS_24BIT; stripe_pos_rgb++) { |
if (stripe_pos_rgb == circle_position) { |
neorv32_neoled_send_polling(0, circle_color); |
} |
else { |
neorv32_neoled_send_polling(0, 0); // LED off |
} |
} |
if (circle_position == (NUM_LEDS_24BIT-1)) { |
circle_position = 0; |
circle_color = (circle_color << 8) | ((circle_color >> 16) & 0xff); |
} |
else { |
circle_position++; |
} |
|
|
// RGBW LEDs: knight rider! |
if ((flash_position == (NUM_LEDS_32BIT-1)) || (flash_position == 0)) { |
flash_direction = -flash_direction; |
} |
for (stripe_pos_rgbw=0; stripe_pos_rgbw<NUM_LEDS_32BIT; stripe_pos_rgbw++) { |
if (stripe_pos_rgbw == flash_position) { |
neorv32_neoled_send_polling(1, 0x00000004); // white dot using the dedicated white LED chip |
} |
else { |
neorv32_neoled_send_polling(1, 0); // LED off |
} |
} |
flash_position += flash_direction; |
|
|
// delay between frames; also used to "send" ws2812.reset command |
neorv32_cpu_delay_ms(100); |
} |
|
return 0; |
} |
/neorv32/trunk/sw/example/demo_neopixel/makefile
0,0 → 1,338
################################################################################################# |
# << NEORV32 - Application Makefile >> # |
# ********************************************************************************************* # |
# Make sure to add the riscv GCC compiler's bin folder to your PATH environment variable. # |
# ********************************************************************************************* # |
# BSD 3-Clause License # |
# # |
# Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
# # |
# Redistribution and use in source and binary forms, with or without modification, are # |
# permitted provided that the following conditions are met: # |
# # |
# 1. Redistributions of source code must retain the above copyright notice, this list of # |
# conditions and the following disclaimer. # |
# # |
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
# conditions and the following disclaimer in the documentation and/or other materials # |
# provided with the distribution. # |
# # |
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
# endorse or promote products derived from this software without specific prior written # |
# permission. # |
# # |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
# OF THE POSSIBILITY OF SUCH DAMAGE. # |
# ********************************************************************************************* # |
# The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # |
################################################################################################# |
|
|
# ***************************************************************************** |
# USER CONFIGURATION |
# ***************************************************************************** |
# User's application sources (*.c, *.cpp, *.s, *.S); add additional files here |
APP_SRC ?= $(wildcard ./*.c) $(wildcard ./*.s) $(wildcard ./*.cpp) $(wildcard ./*.S) |
|
# User's application include folders (don't forget the '-I' before each entry) |
APP_INC ?= -I . |
# User's application include folders - for assembly files only (don't forget the '-I' before each entry) |
ASM_INC ?= -I . |
|
# Optimization |
EFFORT ?= -Os |
|
# Compiler toolchain |
RISCV_TOOLCHAIN ?= riscv32-unknown-elf |
|
# CPU architecture and ABI |
MARCH ?= -march=rv32i |
MABI ?= -mabi=ilp32 |
|
# User flags for additional configuration (will be added to compiler flags) |
USER_FLAGS ?= |
|
# Serial port for executable upload via bootloer |
COM_PORT ?= /dev/ttyUSB0 |
|
# Relative or absolute path to the NEORV32 home folder |
NEORV32_HOME ?= ../../.. |
# ***************************************************************************** |
|
|
|
# ----------------------------------------------------------------------------- |
# NEORV32 framework |
# ----------------------------------------------------------------------------- |
# Path to NEORV32 linker script and startup file |
NEORV32_COM_PATH = $(NEORV32_HOME)/sw/common |
# Path to main NEORV32 library include files |
NEORV32_INC_PATH = $(NEORV32_HOME)/sw/lib/include |
# Path to main NEORV32 library source files |
NEORV32_SRC_PATH = $(NEORV32_HOME)/sw/lib/source |
# Path to NEORV32 executable generator |
NEORV32_EXG_PATH = $(NEORV32_HOME)/sw/image_gen |
# Path to NEORV32 core rtl folder |
NEORV32_RTL_PATH = $(NEORV32_HOME)/rtl/core |
# Marker file to check for NEORV32 home folder |
NEORV32_HOME_MARKER = $(NEORV32_INC_PATH)/neorv32.h |
|
# Core libraries (peripheral and CPU drivers) |
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c) |
# Application start-up code |
CORE_SRC += $(NEORV32_COM_PATH)/crt0.S |
|
# Linker script |
LD_SCRIPT = $(NEORV32_COM_PATH)/neorv32.ld |
|
# Main output files |
APP_EXE = neorv32_exe.bin |
APP_ASM = main.asm |
APP_IMG = neorv32_application_image.vhd |
BOOT_IMG = neorv32_bootloader_image.vhd |
|
|
# ----------------------------------------------------------------------------- |
# Sources and objects |
# ----------------------------------------------------------------------------- |
# Define all sources |
SRC = $(APP_SRC) |
SRC += $(CORE_SRC) |
|
# Define all object files |
OBJ = $(SRC:%=%.o) |
|
|
# ----------------------------------------------------------------------------- |
# Tools and flags |
# ----------------------------------------------------------------------------- |
# Compiler tools |
CC = $(RISCV_TOOLCHAIN)-gcc |
OBJDUMP = $(RISCV_TOOLCHAIN)-objdump |
OBJCOPY = $(RISCV_TOOLCHAIN)-objcopy |
SIZE = $(RISCV_TOOLCHAIN)-size |
|
# Host native compiler |
CC_X86 = g++ -Wall -O -g |
|
# NEORV32 executable image generator |
IMAGE_GEN = $(NEORV32_EXG_PATH)/image_gen |
|
# Compiler & linker flags |
CC_OPTS = $(MARCH) $(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles |
CC_OPTS += -Wl,--gc-sections -lm -lc -lgcc -lc |
# This accelerates instruction fetch after branches when C extension is enabled (irrelevant when C extension is disabled) |
CC_OPTS += -falign-functions=4 -falign-labels=4 -falign-loops=4 -falign-jumps=4 |
CC_OPTS += $(USER_FLAGS) |
|
|
# ----------------------------------------------------------------------------- |
# Application output definitions |
# ----------------------------------------------------------------------------- |
.PHONY: check info help elf_info clean clean_all bootloader |
.DEFAULT_GOAL := help |
|
# 'compile' is still here for compatibility |
exe: $(APP_ASM) $(APP_EXE) |
compile: $(APP_ASM) $(APP_EXE) |
install: $(APP_ASM) $(APP_IMG) |
all: $(APP_ASM) $(APP_EXE) $(APP_IMG) |
|
# Check if making bootloader |
# Use different base address and legth for instruction memory/"rom" (BOOTMEM instead of IMEM) |
# Also define "make_bootloader" for crt0.S |
target bootloader: CC_OPTS += -Wl,--defsym=make_bootloader=1 -Dmake_bootloader |
|
|
# ----------------------------------------------------------------------------- |
# Image generator targets |
# ----------------------------------------------------------------------------- |
# install/compile tools |
$(IMAGE_GEN): $(NEORV32_EXG_PATH)/image_gen.cpp |
@echo Compiling $(IMAGE_GEN) |
@$(CC_X86) $< -o $(IMAGE_GEN) |
|
|
# ----------------------------------------------------------------------------- |
# General targets: Assemble, compile, link, dump |
# ----------------------------------------------------------------------------- |
# Compile app *.s sources (assembly) |
%.s.o: %.s |
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@ |
|
# Compile app *.S sources (assembly + C pre-processor) |
%.S.o: %.S |
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@ |
|
# Compile app *.c sources |
%.c.o: %.c |
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@ |
|
# Compile app *.cpp sources |
%.cpp.o: %.cpp |
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@ |
|
# Link object files and show memory utilization |
main.elf: $(OBJ) |
@$(CC) $(CC_OPTS) -T $(LD_SCRIPT) $(OBJ) -o $@ |
@echo "Memory utilization:" |
@$(SIZE) main.elf |
|
# Assembly listing file (for debugging) |
$(APP_ASM): main.elf |
@$(OBJDUMP) -d -S -z $< > $@ |
|
# Generate final executable from .text + .rodata + .data (in THIS order!) |
main.bin: main.elf $(APP_ASM) |
@$(OBJCOPY) -I elf32-little $< -j .text -O binary text.bin |
@$(OBJCOPY) -I elf32-little $< -j .rodata -O binary rodata.bin |
@$(OBJCOPY) -I elf32-little $< -j .data -O binary data.bin |
@cat text.bin rodata.bin data.bin > $@ |
@rm -f text.bin rodata.bin data.bin |
|
|
# ----------------------------------------------------------------------------- |
# Application targets: Generate binary executable, install (as VHDL file) |
# ----------------------------------------------------------------------------- |
# Generate NEORV32 executable image for upload via bootloader |
$(APP_EXE): main.bin $(IMAGE_GEN) |
@set -e |
@$(IMAGE_GEN) -app_bin $< $@ $(shell basename $(CURDIR)) |
@echo "Executable ($(APP_EXE)) size in bytes:" |
@wc -c < $(APP_EXE) |
|
# Generate NEORV32 executable VHDL boot image |
$(APP_IMG): main.bin $(IMAGE_GEN) |
@set -e |
@$(IMAGE_GEN) -app_img $< $@ $(shell basename $(CURDIR)) |
@echo "Installing application image to $(NEORV32_RTL_PATH)/$(APP_IMG)" |
@cp $(APP_IMG) $(NEORV32_RTL_PATH)/. |
|
|
# ----------------------------------------------------------------------------- |
# Bootloader targets |
# ----------------------------------------------------------------------------- |
# Create and install bootloader VHDL init image |
$(BOOT_IMG): main.bin $(IMAGE_GEN) |
@set -e |
@$(IMAGE_GEN) -bld_img $< $(BOOT_IMG) $(shell basename $(CURDIR)) |
@echo "Installing bootloader image to $(NEORV32_RTL_PATH)/$(BOOT_IMG)" |
@cp $(BOOT_IMG) $(NEORV32_RTL_PATH)/. |
|
# Just an alias that |
bootloader: $(BOOT_IMG) |
|
|
# ----------------------------------------------------------------------------- |
# Check toolchain |
# ----------------------------------------------------------------------------- |
check: $(IMAGE_GEN) |
@echo "---------------- Check: NEORV32_HOME folder ----------------" |
ifneq ($(shell [ -e $(NEORV32_HOME_MARKER) ] && echo 1 || echo 0 ), 1) |
$(error NEORV32_HOME folder not found!) |
endif |
@echo "NEORV32_HOME: $(NEORV32_HOME)" |
@echo "---------------- Check: $(CC) ----------------" |
@$(CC) -v |
@echo "---------------- Check: $(OBJDUMP) ----------------" |
@$(OBJDUMP) -V |
@echo "---------------- Check: $(OBJCOPY) ----------------" |
@$(OBJCOPY) -V |
@echo "---------------- Check: $(SIZE) ----------------" |
@$(SIZE) -V |
@echo "---------------- Check: NEORV32 image_gen ----------------" |
@$(IMAGE_GEN) -help |
@echo "---------------- Check: Native GCC ----------------" |
@$(CC_X86) -v |
@echo |
@echo "Toolchain check OK" |
|
|
# ----------------------------------------------------------------------------- |
# Upload executable via serial port to bootloader |
# ----------------------------------------------------------------------------- |
upload: $(APP_EXE) |
@sh $(NEORV32_EXG_PATH)/uart_upload.sh $(COM_PORT) $(APP_EXE) |
|
|
# ----------------------------------------------------------------------------- |
# Show configuration |
# ----------------------------------------------------------------------------- |
info: |
@echo "---------------- Info: Project ----------------" |
@echo "Project folder: $(shell basename $(CURDIR))" |
@echo "Source files: $(APP_SRC)" |
@echo "Include folder(s): $(APP_INC)" |
@echo "ASM include folder(s): $(ASM_INC)" |
@echo "---------------- Info: NEORV32 ----------------" |
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)" |
@echo "IMAGE_GEN: $(IMAGE_GEN)" |
@echo "Core source files:" |
@echo "$(CORE_SRC)" |
@echo "Core include folder:" |
@echo "$(NEORV32_INC_PATH)" |
@echo "---------------- Info: Objects ----------------" |
@echo "Project object files:" |
@echo "$(OBJ)" |
@echo "---------------- Info: RISC-V CPU ----------------" |
@echo "MARCH: $(MARCH)" |
@echo "MABI: $(MABI)" |
@echo "---------------- Info: Toolchain ----------------" |
@echo "Toolchain: $(RISCV_TOLLCHAIN)" |
@echo "CC: $(CC)" |
@echo "OBJDUMP: $(OBJDUMP)" |
@echo "OBJCOPY: $(OBJCOPY)" |
@echo "SIZE: $(SIZE)" |
@echo "---------------- Info: Compiler Libraries ----------------" |
@echo "LIBGCC:" |
@$(CC) -print-libgcc-file-name |
@echo "SEARCH-DIRS:" |
@$(CC) -print-search-dirs |
@echo "---------------- Info: Flags ----------------" |
@echo "USER_FLAGS: $(USER_FLAGS)" |
@echo "CC_OPTS: $(CC_OPTS)" |
@echo "---------------- Info: Host Native GCC Flags ----------------" |
@echo "CC_X86: $(CC_X86)" |
|
|
# ----------------------------------------------------------------------------- |
# Show final ELF details (just for debugging) |
# ----------------------------------------------------------------------------- |
elf_info: main.elf |
@$(OBJDUMP) -x main.elf |
|
|
# ----------------------------------------------------------------------------- |
# Help |
# ----------------------------------------------------------------------------- |
help: |
@echo "<<< NEORV32 Application Makefile >>>" |
@echo "Make sure to add the bin folder of RISC-V GCC to your PATH variable." |
@echo "Targets:" |
@echo " help - show this text" |
@echo " check - check toolchain" |
@echo " info - show makefile/toolchain configuration" |
@echo " exe - compile and generate <neorv32_exe.bin> executable for upload via bootloader" |
@echo " install - compile, generate and install VHDL IMEM boot image (for application)" |
@echo " all - compile and generate <neorv32_exe.bin> executable for upload via bootloader and generate and install VHDL IMEM boot image (for application)" |
@echo " clean - clean up project" |
@echo " clean_all - clean up project, core libraries and image generator" |
@echo " bootloader - compile, generate and install VHDL BOOTROM boot image (for bootloader only!)" |
@echo " upload - upload <neorv32_exe.bin> executable via serial port <COM_PORT> to bootloader" |
|
|
# ----------------------------------------------------------------------------- |
# Clean up |
# ----------------------------------------------------------------------------- |
clean: |
@rm -f *.elf *.o *.bin *.out *.asm *.vhd |
|
clean_all: clean |
@rm -f $(OBJ) $(IMAGE_GEN) |
/neorv32/trunk/sw/lib/include/neorv32.h
424,7 → 424,9
CSR_MISA_A_EXT = 0, /**< CPU misa CSR (0): A: Atomic instructions CPU extension available (r/-)*/ |
CSR_MISA_B_EXT = 1, /**< CPU misa CSR (1): B: Bit manipulation CPU extension available (r/-)*/ |
CSR_MISA_C_EXT = 2, /**< CPU misa CSR (2): C: Compressed instructions CPU extension available (r/-)*/ |
CSR_MISA_D_EXT = 3, /**< CPU misa CSR (3): D: Double-precision floating-point extension available (r/-)*/ |
CSR_MISA_E_EXT = 4, /**< CPU misa CSR (4): E: Embedded CPU extension available (r/-) */ |
CSR_MISA_F_EXT = 5, /**< CPU misa CSR (5): F: Single-precision floating-point extension available (r/-)*/ |
CSR_MISA_I_EXT = 8, /**< CPU misa CSR (8): I: Base integer ISA CPU extension available (r/-) */ |
CSR_MISA_M_EXT = 12, /**< CPU misa CSR (12): M: Multiplier/divider CPU extension available (r/-)*/ |
CSR_MISA_U_EXT = 20, /**< CPU misa CSR (20): U: User mode CPU extension available (r/-)*/ |
507,7 → 509,7
|
|
/**********************************************************************//** |
* Processor clock prescalers |
* Processor clock prescalers select |
**************************************************************************/ |
enum NEORV32_CLOCK_PRSC_enum { |
CLK_PRSC_2 = 0, /**< CPU_CLK (from clk_i top signal) / 2 */ |
931,6 → 933,53
|
|
/**********************************************************************//** |
* @name IO Device: Smart LED Hardware Interface (NEOLED) |
**************************************************************************/ |
/**@{*/ |
/** NEOLED control register (r/w) */ |
#define NEOLED_CT (*(IO_REG32 0xFFFFFFD8UL)) // r/w: control register |
/** NEOLED TX data register (-/w) */ |
#define NEOLED_DATA (*(IO_REG32 0xFFFFFFDCUL)) // -/w: TX data register |
|
/** NEOLED control register bits */ |
enum NEORV32_NEOLED_CT_enum { |
NEOLED_CT_EN = 0, /**< NEOLED control register(0) (r/w): NEOLED global enable */ |
NEOLED_CT_MODE = 1, /**< NEOLED control register(1) (r/w): TX mode (0=24-bit, 1=32-bit) */ |
NEOLED_CT_BSCON = 2, /**< NEOLED control register(2) (r/w): buffer status configuration -> busy_flag/IRQ config (0=at least one free entry, 1=whole buffer empty) */ |
NEOLED_CT_PRSC0 = 3, /**< NEOLED control register(3) (r/w): Clock prescaler select bit 0 (pulse-clock speed select) */ |
NEOLED_CT_PRSC1 = 4, /**< NEOLED control register(4) (r/w): Clock prescaler select bit 1 (pulse-clock speed select) */ |
NEOLED_CT_PRSC2 = 5, /**< NEOLED control register(5) (r/w): Clock prescaler select bit 2 (pulse-clock speed select) */ |
// |
NEOLED_CT_BUFS_0 = 6, /**< NEOLED control register(6) (r/-): log2(tx buffer size) bit 0 */ |
NEOLED_CT_BUFS_1 = 7, /**< NEOLED control register(7) (r/-): log2(tx buffer size) bit 1 */ |
NEOLED_CT_BUFS_2 = 8, /**< NEOLED control register(8) (r/-): log2(tx buffer size) bit 2 */ |
NEOLED_CT_BUFS_3 = 9, /**< NEOLED control register(9) (r/-): log2(tx buffer size) bit 3 */ |
// |
NEOLED_CT_T_TOT_0 = 10, /**< NEOLED control register(10) (r/w): pulse-clock ticks per total period bit 0 */ |
NEOLED_CT_T_TOT_1 = 11, /**< NEOLED control register(11) (r/w): pulse-clock ticks per total period bit 1 */ |
NEOLED_CT_T_TOT_2 = 12, /**< NEOLED control register(12) (r/w): pulse-clock ticks per total period bit 2 */ |
NEOLED_CT_T_TOT_3 = 13, /**< NEOLED control register(13) (r/w): pulse-clock ticks per total period bit 3 */ |
NEOLED_CT_T_TOT_4 = 14, /**< NEOLED control register(14) (r/w): pulse-clock ticks per total period bit 4 */ |
// |
NEOLED_CT_T_ZERO_H_0 = 15, /**< NEOLED control register(15) (r/w): pulse-clock ticks per ZERO high-time bit 0 */ |
NEOLED_CT_T_ZERO_H_1 = 16, /**< NEOLED control register(16) (r/w): pulse-clock ticks per ZERO high-time bit 1 */ |
NEOLED_CT_T_ZERO_H_2 = 17, /**< NEOLED control register(17) (r/w): pulse-clock ticks per ZERO high-time bit 2 */ |
NEOLED_CT_T_ZERO_H_3 = 18, /**< NEOLED control register(18) (r/w): pulse-clock ticks per ZERO high-time bit 3 */ |
NEOLED_CT_T_ZERO_H_4 = 19, /**< NEOLED control register(19) (r/w): pulse-clock ticks per ZERO high-time bit 4 */ |
// |
NEOLED_CT_T_ONE_H_0 = 20, /**< NEOLED control register(20) (r/w): pulse-clock ticks per ONE high-time bit 0 */ |
NEOLED_CT_T_ONE_H_1 = 21, /**< NEOLED control register(21) (r/w): pulse-clock ticks per ONE high-time bit 1 */ |
NEOLED_CT_T_ONE_H_2 = 22, /**< NEOLED control register(22) (r/w): pulse-clock ticks per ONE high-time bit 2 */ |
NEOLED_CT_T_ONE_H_3 = 23, /**< NEOLED control register(23) (r/w): pulse-clock ticks per ONE high-time bit 3 */ |
NEOLED_CT_T_ONE_H_4 = 24, /**< NEOLED control register(24) (r/w): pulse-clock ticks per ONE high-time bit 4 */ |
// |
NEOLED_CT_TX_STATUS = 30, /**< NEOLED control register(30) (r/-): serial transmit engine still busy when set */ |
NEOLED_CT_BUSY = 31 /**< NEOLED control register(31) (r/-): busy / buffer status flag (configured via #NEOLED_CT_BSCON) */ |
}; |
/**@}*/ |
|
|
/**********************************************************************//** |
* @name IO Device: System Configuration Info Memory (SYSINFO) |
**************************************************************************/ |
/**@{*/ |
974,7 → 1023,8
SYSINFO_FEATURES_IO_CFS = 23, /**< SYSINFO_FEATURES (23) (r/-): Custom functions subsystem implemented when 1 (via IO_CFS_EN generic) */ |
SYSINFO_FEATURES_IO_TRNG = 24, /**< SYSINFO_FEATURES (24) (r/-): True random number generator implemented when 1 (via IO_TRNG_EN generic) */ |
SYSINFO_FEATURES_IO_NCO = 25, /**< SYSINFO_FEATURES (25) (r/-): Numerically-controlled oscillator implemented when 1 (via IO_NCO_EN generic) */ |
SYSINFO_FEATURES_IO_UART1 = 26 /**< SYSINFO_FEATURES (26) (r/-): Secondary universal asynchronous receiver/transmitter 1 implemented when 1 (via IO_UART1_EN generic) */ |
SYSINFO_FEATURES_IO_UART1 = 26, /**< SYSINFO_FEATURES (26) (r/-): Secondary universal asynchronous receiver/transmitter 1 implemented when 1 (via IO_UART1_EN generic) */ |
SYSINFO_FEATURES_IO_NEOLED = 27 /**< SYSINFO_FEATURES (27) (r/-): NeoPixel-compatible smart LED interface implemented when 1 (via IO_NEOLED_EN generic) */ |
}; |
|
/**********************************************************************//** |
1017,6 → 1067,7
#include "neorv32_gpio.h" |
#include "neorv32_mtime.h" |
#include "neorv32_nco.h" |
#include "neorv32_neoled.h" |
#include "neorv32_pwm.h" |
#include "neorv32_spi.h" |
#include "neorv32_trng.h" |
/neorv32/trunk/sw/lib/include/neorv32_neoled.h
0,0 → 1,57
// ################################################################################################# |
// # << NEORV32: neorv32_neoled.h - Smart LED Interface (NEOLED) HW Driver >> # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. # |
// # # |
// # Redistribution and use in source and binary forms, with or without modification, are # |
// # permitted provided that the following conditions are met: # |
// # # |
// # 1. Redistributions of source code must retain the above copyright notice, this list of # |
// # conditions and the following disclaimer. # |
// # # |
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
// # conditions and the following disclaimer in the documentation and/or other materials # |
// # provided with the distribution. # |
// # # |
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
// # endorse or promote products derived from this software without specific prior written # |
// # permission. # |
// # # |
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
// # OF THE POSSIBILITY OF SUCH DAMAGE. # |
// # ********************************************************************************************* # |
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # |
// ################################################################################################# |
|
|
/**********************************************************************//** |
* @file neorv32_neoled.h |
* @author Stephan Nolting |
* @brief Smart LED Interface (NEOLED) HW driver header file. |
* |
* @note These functions should only be used if the NEOLED unit was synthesized (IO_NEOLED_EN = true). |
**************************************************************************/ |
|
#ifndef neorv32_neoled_h |
#define neorv32_neoled_h |
|
// prototypes |
int neorv32_neoled_available(void); |
void neorv32_neoled_setup_raw(uint32_t bs_config, uint32_t prsc, uint32_t t_total, uint32_t t_high_zero, uint32_t t_high_one); |
void neorv32_neoled_setup_ws2812(uint32_t bs_config); |
void neorv32_neoled_enable(void); |
void neorv32_neoled_disable(void); |
void neorv32_neoled_send_polling(uint32_t mode, uint32_t data); |
void neorv32_neoled_send_direct(uint32_t mode, uint32_t data); |
uint32_t neorv32_neoled_get_buffer_size(void); |
|
#endif // neorv32_neoled_h |
/neorv32/trunk/sw/lib/source/neorv32_neoled.c
0,0 → 1,231
// ################################################################################################# |
// # << NEORV32: neorv32_neoled.c - Smart LED Interface (NEOLED) HW Driver >> # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. # |
// # # |
// # Redistribution and use in source and binary forms, with or without modification, are # |
// # permitted provided that the following conditions are met: # |
// # # |
// # 1. Redistributions of source code must retain the above copyright notice, this list of # |
// # conditions and the following disclaimer. # |
// # # |
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
// # conditions and the following disclaimer in the documentation and/or other materials # |
// # provided with the distribution. # |
// # # |
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
// # endorse or promote products derived from this software without specific prior written # |
// # permission. # |
// # # |
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
// # OF THE POSSIBILITY OF SUCH DAMAGE. # |
// # ********************************************************************************************* # |
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # |
// ################################################################################################# |
|
|
/**********************************************************************//** |
* @file neorv32_neoled.c |
* @author Stephan Nolting |
* @brief Smart LED Interface (NEOLED) HW driver source file. |
* |
* @note These functions should only be used if the NEOLED unit was synthesized (IO_NEOLED_EN = true). |
**************************************************************************/ |
|
#include "neorv32.h" |
#include "neorv32_neoled.h" |
|
|
/**********************************************************************//** |
* Check if NEOLED unit was synthesized. |
* |
* @return 0 if NEOLED was not synthesized, 1 if NEOLED is available. |
**************************************************************************/ |
int neorv32_neoled_available(void) { |
|
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_NEOLED)) { |
return 1; |
} |
else { |
return 0; |
} |
} |
|
|
/**********************************************************************//** |
* Enable and configure NEOLED controller. The NEOLED control register bits are listed in #NEORV32_NEOLED_CT_enum. |
* This function performs a "raw" configuration (just configuraing the according control register bit). |
* |
* @param[in] bs_config Busy flag / IRQ configuration (0 = at least one free entry, 1 = whole buffer empty). |
* @param[in] prsc Clock prescaler select (0..7). See #NEORV32_CLOCK_PRSC_enum. |
* @param[in] t_total Number of pre-scaled clock ticks for total bit period (0..31). |
* @param[in] t_high_zero Number of pre-scaled clock ticks to generate high-time for sending a '0' (0..31). |
* @param[in] t_high_one Number of pre-scaled clock ticks to generate high-time for sending a '1' (0..31). |
**************************************************************************/ |
void neorv32_neoled_setup_raw(uint32_t bs_config, uint32_t prsc, uint32_t t_total, uint32_t t_high_zero, uint32_t t_high_one) { |
|
NEOLED_CT = 0; // reset |
|
// module enable |
uint32_t ct_enable = 1 << NEOLED_CT_EN; |
|
// busy flag / IRQ config |
uint32_t ct_bs_config = (bs_config & 0x1) << NEOLED_CT_BSCON; |
|
// clock pre-scaler |
uint32_t ct_prsc = (prsc & 0x7) << NEOLED_CT_PRSC0; |
|
// serial data output: total period length for one bit |
uint32_t ct_t_total = (t_total & 0x1f) << NEOLED_CT_T_TOT_0; |
|
// serial data output: high-time for sending a '0' |
uint32_t ct_t_zero = (t_high_zero & 0x1f) << NEOLED_CT_T_ZERO_H_0; |
|
// serial data output: high-time for sending a '1' |
uint32_t ct_t_one = (t_high_one & 0x1f) << NEOLED_CT_T_ONE_H_0; |
|
// set new configuration |
NEOLED_CT = ct_enable | ct_bs_config | ct_prsc | ct_t_total | ct_t_zero | ct_t_one; |
} |
|
|
/**********************************************************************//** |
* Configure NEOLED controller for using WS2812 LEDs (NeoPixel-compatible). This function computes |
* all the required timings and finally calls #neorv32_neoled_setup_raw. |
* |
* @note WS2812 timing: T_period = 1.2us, T_high_zero = 0.4us, T_high_one = 0.8us. Change the constants if required. |
* @note This function uses the SYSINFO_CLK value (from the SYSINFO HW module) to do the timing computations. |
* |
* @param[in] bs_config Busy flag / IRQ configuration (0 = at least one free entry, 1 = whole buffer empty). |
**************************************************************************/ |
void neorv32_neoled_setup_ws2812(uint32_t bs_config) { |
|
// WS2812 timing |
const uint32_t T_TOTAL_C = 1200; // ns |
const uint32_t T_H_ZERO_C = 400; // ns |
const uint32_t T_H_ONE_C = 800; // ns |
|
// processor clock pre-scalers |
const uint32_t CLK_PRSC_FACTOR_LUT[8] = {2, 4, 8, 64, 128, 1024, 2048, 4096}; |
|
// get base clock period in multiples of 0.5ns |
uint32_t t_clock_x500ps = (2 * 1000 * 1000 * 1000) / SYSINFO_CLK; |
|
// compute LED interface timing parameters |
uint32_t t_base = 0; |
uint32_t t_total = 0; |
uint32_t t_high_zero = 0; |
uint32_t t_high_one = 0; |
uint32_t clk_prsc_sel = CLK_PRSC_2; // initial prsc = CLK/2 |
uint32_t clk_prsc_fac = 0; // corresponding clock scaling factor |
|
//neorv32_uart0_printf("\nNEOLED.T_clk: %u x 500ps\n", t_clock_x500ps); // DEBUG |
|
while (clk_prsc_sel < 7) { |
clk_prsc_fac = CLK_PRSC_FACTOR_LUT[clk_prsc_sel & 7]; |
|
//neorv32_uart0_printf("NEOLED.clk_prsc: %u\n", clk_prsc_fac); // DEBUG |
|
t_base = t_clock_x500ps * clk_prsc_fac; |
|
//neorv32_uart0_printf("NEOLED.t_base: %u x 0.5ns\n", t_base); // DEBUG |
|
// compute bit period and high-times for sending a 0 or 1 |
t_total = (2*T_TOTAL_C) / t_base; |
t_high_zero = (2*T_H_ZERO_C) / t_base; |
t_high_one = (2*T_H_ONE_C) / t_base; |
|
//neorv32_uart0_printf("NEOLED.t_total: %u\n", t_total); // DEBUG |
//neorv32_uart0_printf("NEOLED.t_high_zero: %u\n", t_high_zero); // DEBUG |
//neorv32_uart0_printf("NEOLED.t_high_one: %u\n", t_high_one); // DEBUG |
|
if ((t_base == 0) || (t_total >= 32) || (t_high_zero == 0) || (t_high_one == 0)) { // out of range or invalid resolution |
clk_prsc_sel++; // try next-higher clock prescaler |
} |
else { |
break; |
} |
} |
|
// set raw configuration |
neorv32_neoled_setup_raw(bs_config, clk_prsc_sel, t_total, t_high_zero, t_high_one); |
} |
|
|
/**********************************************************************//** |
* Enable NEOLED controller. |
**************************************************************************/ |
void neorv32_neoled_enable(void) { |
|
NEOLED_CT |= ((uint32_t)(1 << NEOLED_CT_EN)); |
} |
|
|
/**********************************************************************//** |
* Disable NEOLED controller. |
**************************************************************************/ |
void neorv32_neoled_disable(void) { |
|
NEOLED_CT &= ~((uint32_t)(1 << NEOLED_CT_EN)); |
} |
|
|
/**********************************************************************//** |
* Send single data word to NEOLED module. |
* |
* @warning This function is blocking as it polls the NEOLED busy flag. |
* |
* @param[in] mode 0 = 24-bit mode (RGB), 1 = 32-bit mode (RGBW) |
* @param[in] data 24-bit RGB or 32-bit RGBW data |
**************************************************************************/ |
void neorv32_neoled_send_polling(uint32_t mode, uint32_t data) { |
|
while(NEOLED_CT & (1 << NEOLED_CT_BUSY)); // wait for busy flag to clear |
|
neorv32_neoled_send_direct(mode, data); |
} |
|
|
/**********************************************************************//** |
* Send single data word to NEOLED module. |
* |
* @warning This function used NO busy checks at all! |
* @note This function can be called several times in a row to fill the TX buffer (when busy_flag is cleared and bscon = 1). |
* |
* @param[in] mode 0 = 24-bit mode (RGB), 1 = 32-bit mode (RGBW) |
* @param[in] data 24-bit RGB or 32-bit RGBW data |
**************************************************************************/ |
void neorv32_neoled_send_direct(uint32_t mode, uint32_t data) { |
|
// configure TX mode (data size) |
uint32_t ctrl = NEOLED_CT; |
ctrl &= ~(0b1 << NEOLED_CT_MODE); // clear current mode |
ctrl |= ((mode & 1) << NEOLED_CT_MODE); // set new mode |
NEOLED_CT = ctrl; |
|
NEOLED_DATA = data; // send new LED data |
} |
|
|
/**********************************************************************//** |
* Get NEOLED hardware buffer size. |
* |
* @return Number of entries in NEOLED TX buffer. |
**************************************************************************/ |
uint32_t neorv32_neoled_get_buffer_size(void) { |
|
uint32_t tmp = NEOLED_CT; |
tmp = tmp >> NEOLED_CT_BUFS_0; |
tmp = tmp & 0b1111; // insulate buffer size flags |
|
return (1 << tmp); // num entries = pow(2, buffer size flags) |
} |
/neorv32/trunk/sw/lib/source/neorv32_rte.c
55,6 → 55,14
|
|
/**********************************************************************//** |
* Floating-Point extension notifier. |
**************************************************************************/ |
#ifdef __riscv_flen |
#warning Floating-point extension <F> is WORK-IN-PROGRESS and NOT FULLY OPERATIONAL yet! |
#endif |
|
|
/**********************************************************************//** |
* Setup NEORV32 runtime environment. |
* |
* @note This function installs a debug handler for ALL exception and interrupt sources, which |
431,38 → 439,41
|
tmp = SYSINFO_FEATURES; |
|
neorv32_uart_printf("GPIO - "); |
neorv32_uart_printf("GPIO - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_GPIO)); |
|
neorv32_uart_printf("MTIME - "); |
neorv32_uart_printf("MTIME - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_MTIME)); |
|
neorv32_uart_printf("UART0 - "); |
neorv32_uart_printf("UART0 - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART0)); |
|
neorv32_uart_printf("UART1 - "); |
neorv32_uart_printf("UART1 - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART1)); |
|
neorv32_uart_printf("SPI - "); |
neorv32_uart_printf("SPI - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_SPI)); |
|
neorv32_uart_printf("TWI - "); |
neorv32_uart_printf("TWI - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TWI)); |
|
neorv32_uart_printf("PWM - "); |
neorv32_uart_printf("PWM - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_PWM)); |
|
neorv32_uart_printf("WDT - "); |
neorv32_uart_printf("WDT - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_WDT)); |
|
neorv32_uart_printf("TRNG - "); |
neorv32_uart_printf("TRNG - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TRNG)); |
|
neorv32_uart_printf("CFS - "); |
neorv32_uart_printf("CFS - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFS)); |
|
neorv32_uart_printf("NCO - "); |
neorv32_uart_printf("NCO - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_NCO)); |
|
neorv32_uart_printf("NEOLED - "); |
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_NEOLED)); |
} |
|
|
644,6 → 655,10
misa_cc |= 1 << CSR_MISA_C_EXT; |
#endif |
|
#if (__riscv_flen == 64) |
misa_cc |= 1 << CSR_MISA_D_EXT; |
#endif |
|
#ifdef __riscv_32e |
misa_cc |= 1 << CSR_MISA_E_EXT; |
#else |
650,6 → 665,10
misa_cc |= 1 << CSR_MISA_I_EXT; |
#endif |
|
#if (__riscv_flen == 32) |
misa_cc |= 1 << CSR_MISA_F_EXT; |
#endif |
|
#ifdef __riscv_mul |
misa_cc |= 1 << CSR_MISA_M_EXT; |
#endif |
/neorv32/trunk/sw/lib/source/neorv32_spi.c
89,7 → 89,7
|
|
/**********************************************************************//** |
* Disable and SPI controller. |
* Disable SPI controller. |
**************************************************************************/ |
void neorv32_spi_disable(void) { |
|
/neorv32/trunk/CHANGELOG.md
14,6 → 14,10
|
| Date (*dd.mm.yyyy*) | Version | Comment | |
|:----------:|:-------:|:--------| |
| 07.03.2021 | 1.5.2.4 | :sparkles: added new IO/peripheral module: **Smart LED Interface (NEOLED)** to interface intelligent LEDs (WS2812/WS2811/NeoPixel(c) compatible; supports RGB and RGBW LEDs in *parallel*) with internal TX buffer; new top generics: `IO_NEOLED_EN`: implement NEOLED interface when *true*; new top signals: `neoled_o`: single-wire async. serial data interface; FIFO re-fill interrupt via *fast interrupt request channel 9* `FIRQ9`; added new "NEOLED" section to data sheet; added SW driver library and simple NEOLED example program (`sw/example/demo_neopixel`) | |
| 06.03.2021 | 1.5.2.3 | clean-up of CPU control code: fixed minor bug in F-exension's instruction decoding; changed coding style for CSR write access (old version might have caused "inferring latch..." warning in Intel Quartus); fixed default values for CSRs when according extensions are disabled | |
| 04.03.2021 | 1.5.2.2 | added two new generics to configure CFS IO conduit sizes (implementing [issue #13](https://github.com/stnolting/neorv32/issues/13)): `IO_CFS_IN_SIZE` - type: `positive`, configures the size of `cfs_in_i` signal; `IO_CFS_OUT_SIZE` - type: `positive`, configures the size of `cfs_out_o` signal; minor edits to floating-point CPU infrastructure | |
| 03.03.2021 | 1.5.2.1 | added CPU core infrastructure for *upcoming* single-precision floating-point extension `F`; :warning: **floating-point extension is NOT OPERATIONAL YET!** added new rtl file for the floating-point unit `rtl/core/neorv32_cpu_cp_fpu.vhd` (blank template!) | |
| 01.03.2021 | [**:rocket:1.5.2.0**](https://github.com/stnolting/neorv32/releases/tag/v1.5.2.0) | **New release** | |
| 27.02.2021 | 1.5.1.11 | :bug: fixed several small bugs in *bitmanipulation extension* instruction decoding (not all `B` instructions triggered and *illegal instruction exception* when B-extension = disabled) | |
| 25.02.2021 | 1.5.1.10 | :bug: fixed bugs in UART RTS/CTS hardware control flow - the new setup was verified on real hardware; added double-buffering to UART RX engine | |
/neorv32/trunk/README.md
3,7 → 3,7
# The NEORV32 RISC-V Processor |
|
[![Processor Check](https://github.com/stnolting/neorv32/workflows/Processor%20Check/badge.svg)](https://github.com/stnolting/neorv32/actions?query=workflow%3A%22Processor+Check%22) |
[![RISC-V Compliance](https://github.com/stnolting/neorv32/workflows/RISC-V%20Compliance/badge.svg)](https://github.com/stnolting/neorv32/actions?query=workflow%3A%22RISC-V+Compliance%22) |
[![riscv-arch-test](https://github.com/stnolting/neorv32/actions/workflows/riscv-arch-test.yml/badge.svg)](https://github.com/stnolting/neorv32/actions/workflows/riscv-arch-test.yml) |
[![license](https://img.shields.io/github/license/stnolting/neorv32)](https://github.com/stnolting/neorv32/blob/master/LICENSE) |
[![release](https://img.shields.io/github/v/release/stnolting/neorv32)](https://github.com/stnolting/neorv32/releases) |
|
22,7 → 22,7
## Overview |
|
The NEORV32 Processor is a customizable microcontroller-like system on chip (SoC) that is based |
on the RISC-V-compliant NEORV32 CPU. The processor is intended as *ready-to-go* auxiliary processor within a larger SoC |
on the RISC-V NEORV32 CPU. The processor is intended as *ready-to-go* auxiliary processor within a larger SoC |
designs or as stand-alone custom microcontroller. |
|
:books: For detailed information take a look at the [NEORV32 data sheet (pdf)](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf). |
31,7 → 31,8
:label: The project’s change log is available as [CHANGELOG.md](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md) in the root directory of this repository. |
To see the changes between *stable* releases visit the project's [release page](https://github.com/stnolting/neorv32/releases). |
|
:spiral_notepad: Check out the [project boards](https://github.com/stnolting/neorv32/projects) for a list of current ideas, ToDos, features being planned and work being in-progress. |
:spiral_notepad: Check out the [project boards](https://github.com/stnolting/neorv32/projects) for a list of current **ideas**, |
**TODOs**, features being **planned** and **work-in-progress**. |
|
:bulb: Feel free to open a [new issue](https://github.com/stnolting/neorv32/issues) or start a [new discussion](https://github.com/stnolting/neorv32/discussions) |
if you have questions, comments, ideas or bug-fixes. Check out how to [contribute](#ContributeFeedbackQuestions). |
39,13 → 40,13
|
### Key Features |
|
* RISC-V 32-bit `rv32` [**NEORV32 CPU**](#NEORV32-CPU-Features), compliant to |
* RISC-V 32-bit `rv32` [**NEORV32 CPU**](#NEORV32-CPU-Features), compatible to |
* subset of the *Unprivileged ISA Specification* [(Version 2.2)](https://github.com/stnolting/neorv32/blob/master/docs/riscv-spec.pdf) |
* subset of the *Privileged Architecture Specification* [(Version 1.12-draft)](https://github.com/stnolting/neorv32/blob/master/docs/riscv-privileged.pdf) |
* the [official RISC-V compliance tests](#Status) (*passing*) |
* Configurable RISC-V-compliant CPU extensions |
* the [official RISC-V architecture tests](#Status) (*passing*) |
* Configurable RISC-V-compatible CPU extensions |
* [`A`](#A---Atomic-memory-access-extension) - atomic memory access instructions (optional) |
* [`B`](#B---Bit-manipulation-instructions-extension) - Bit manipulation instructions (optional) |
* [`B`](#B---Bit-manipulation-instructions-extension) - Bit manipulation instructions (optional) :construction: |
* [`C`](#C---Compressed-instructions-extension) - compressed instructions (16-bit) (optional) |
* [`E`](#E---Embedded-CPU-version-extension) - embedded CPU (reduced register file size) (optional) |
* [`I`](#I---Base-integer-instruction-set) - base integer instruction set (always enabled) |
58,10 → 59,11
* [`HPM`](#HPM---Privileged-architecture---Hardware-performance-monitors) - hardware performance monitors (optional) |
* Full-scale RISC-V microcontroller system / **SoC** [**NEORV32 Processor**](#NEORV32-Processor-Features) with optional submodules |
* optional embedded memories (instructions/data/bootloader, RAM/ROM) and caches |
* timers (watch dog, RISC-V-compliant machine timer) |
* timers (watch dog, RISC-V-compatible machine timer) |
* serial interfaces (SPI, TWI, UARTs) |
* general purpose IO and PWM channels |
* external bus interface (Wishbone / [AXI4](#AXI4-Connectivity)) |
* dedicated NeoPixel(c) LED interface |
* subsystem for custom co-processors |
* [more ...](#NEORV32-Processor-Features) |
* Software framework |
95,16 → 97,16
The processor is [synthesizable](#FPGA-Implementation-Results) (tested on *real hardware* using Intel Quartus Prime, Xilinx Vivado and Lattice Radiant/Synplify Pro) and can successfully execute |
all the [provided example programs](https://github.com/stnolting/neorv32/tree/master/sw/example) including the [CoreMark benchmark](#CoreMark-Benchmark). |
|
**RISC-V Compliance**: The processor passes the official `rv32_m/C`, `rv32_m/I`, `rv32_m/M`, `rv32_m/privilege` and `rv32_m/Zifencei` |
[RISC-V compliance](https://github.com/riscv/riscv-compliance) tests. More information regarding the NEORV32 port of the compliance framework can be found in |
[`riscv-compliance/README.md`](https://github.com/stnolting/neorv32/blob/master/riscv-compliance/README.md). |
**RISC-V Architecture Tests**: The processor passes the official `rv32_m/C`, `rv32_m/I`, `rv32_m/M`, `rv32_m/privilege` and `rv32_m/Zifencei` |
[riscv-arch-test](https://github.com/riscv/riscv-arch-test) tests. More information regarding the NEORV32 port of the riscv-arch-test test framework can be found in |
[`riscv-arch-test/README.md`](https://github.com/stnolting/neorv32/blob/master/riscv-arch-test/README.md). |
|
| Project component | CI status | |
|:----------------- |:----------| |
| [NEORV32 processor](https://github.com/stnolting/neorv32) | [![Processor Check](https://github.com/stnolting/neorv32/workflows/Processor%20Check/badge.svg)](https://github.com/stnolting/neorv32/actions?query=workflow%3A%22Processor+Check%22) | |
| [SW Framework Documentation (online @GH-pages)](https://stnolting.github.io/neorv32/files.html) | [![Doc@GitHub-pages](https://github.com/stnolting/neorv32/workflows/Deploy%20SW%20Framework%20Documentation%20to%20GitHub-Pages/badge.svg)](https://stnolting.github.io/neorv32/files.html) | |
| [Pre-built toolchains](https://github.com/stnolting/riscv-gcc-prebuilt) | [![Test Toolchains](https://github.com/stnolting/riscv-gcc-prebuilt/workflows/Test%20Toolchains/badge.svg)](https://github.com/stnolting/riscv-gcc-prebuilt/actions?query=workflow%3A%22Test+Toolchains%22) | |
| [RISC-V compliance test](https://github.com/stnolting/neorv32/blob/master/riscv-compliance/README.md) | [![RISC-V Compliance](https://github.com/stnolting/neorv32/workflows/RISC-V%20Compliance/badge.svg)](https://github.com/stnolting/neorv32/actions?query=workflow%3A%22RISC-V+Compliance%22) | |
| [NEORV32 processor](https://github.com/stnolting/neorv32) | [![Processor Check](https://github.com/stnolting/neorv32/workflows/Processor%20Check/badge.svg)](https://github.com/stnolting/neorv32/actions?query=workflow%3A%22Processor+Check%22) | |
| [SW Framework Documentation (online at GH-pages)](https://stnolting.github.io/neorv32/files.html) | [![Doc@GitHub-pages](https://github.com/stnolting/neorv32/workflows/Deploy%20SW%20Framework%20Documentation%20to%20GitHub-Pages/badge.svg)](https://stnolting.github.io/neorv32/files.html) | |
| [Pre-built toolchains](https://github.com/stnolting/riscv-gcc-prebuilt) | [![Test Toolchains](https://github.com/stnolting/riscv-gcc-prebuilt/workflows/Test%20Toolchains/badge.svg)](https://github.com/stnolting/riscv-gcc-prebuilt/actions?query=workflow%3A%22Test+Toolchains%22) | |
| [RISC-V architecture test](https://github.com/stnolting/neorv32/blob/master/riscv-arch-test/README.md) | [![riscv-arch-test](https://github.com/stnolting/neorv32/actions/workflows/riscv-arch-test.yml/badge.svg)](https://github.com/stnolting/neorv32/actions/workflows/riscv-arch-test.yml) | |
|
|
## Features |
122,28 → 124,29
|
* processor-internal data and instruction memories (**DMEM** / **IMEM**) & cache (**iCACHE**) |
* bootloader (**BOOTLDROM**) with UART console and automatic application boot from SPI flash option |
* machine system timer (**MTIME**), RISC-V-compliant |
* machine system timer (**MTIME**), RISC-V-compatible |
* watchdog timer (**WDT**) |
* two independent universal asynchronous receivers and transmitters (**UART0** & **UART1**) with optional hardware flow control (RTS/CTS) |
* 8/16/24/32-bit serial peripheral interface controller (**SPI**) with 8 dedicated chip select lines |
* two wire serial interface controller (**TWI**), with optional clock-stretching, compatible to the I²C standard |
* general purpose parallel IO port (**GPIO**), 32xOut & 32xIn, with pin-change interrupt |
* 32-bit external bus interface, Wishbone b4 compliant (**WISHBONE**) |
* 32-bit external bus interface, Wishbone b4 compatible (**WISHBONE**) |
* wrapper for **AXI4-Lite Master Interface** (see [AXI Connectivity](#AXI4-Connectivity)) |
* PWM controller with 4 channels and 8-bit duty cycle resolution (**PWM**) |
* ring-oscillator-based true random number generator (**TRNG**) |
* custom functions subsystem (**CFS**) for tightly-coupled custom co-processor extensions |
* numerically-controlled oscillator (**NCO**) with three independent channels |
* smart LED interface (**NEOLED**) - WS2812 / NeoPixel(c) compatible |
* system configuration information memory to check hardware configuration by software (**SYSINFO**) |
|
|
### NEORV32 CPU Features |
|
The NEORV32 CPU is **compliant** to the |
The NEORV32 CPU implements the |
[official RISC-V specifications (2.2)](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/riscv-spec.pdf) including a subset of the |
[RISC-V privileged architecture specifications (1.12-draft)](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/riscv-spec.pdf) |
tested via the [official RISC-V Compliance Test Framework](https://github.com/riscv/riscv-compliance) |
(see [`riscv-compliance/README`](https://github.com/stnolting/neorv32/blob/master/riscv-compliance/README.md)). |
- tested via the [official riscv-arch-test Test Framework](https://github.com/riscv/riscv-arch-test) |
(see [`riscv-arch-test/README`](https://github.com/stnolting/neorv32/blob/master/riscv-arch-test/README.md)). |
|
More information regarding the CPU including a detailed list of the instruction set and the available CSRs can be found in |
the [:page_facing_up: NEORV32 data sheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf). |
167,12 → 170,12
|
#### `B` - Bit manipulation instructions extension |
|
* :warning: Extension is not officially ratified yet by the RISC-V foundation! |
* Implies `Zbb` & `Zbs` sub-extensions (the remaining `B` sub-extensions are not supported yet) |
* :construction: **WORK-IN-PROGRESS** :construction: |
* :warning: The bit-manipulation extension has not been officially ratified yet! |
* Compatible to [v0.94-draft](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/bitmanip-draft.pdf) of the bit manipulation spec |
* Support via intrisc library (see [`sw/example/bit_manipulation`](https://github.com/stnolting/neorv32/tree/master/sw/example/bit_manipulation)) |
* `Zbb` Base instruction set: `CLZ` `CTZ` `CPOP` `SEXT.B` `SEXT.H` `MIN[U]` `MAX[U]` `ANDN` `ORN` `XNOR` `ROL` `ROR[I]` `zext`(*pseudo-instruction* for `PACK rd, rs, zero`) `rev8`(*pseudo-instruction* for `GREVI rd, rs, -8`) `orc.b`(*pseudo-instruction* for `GORCI rd, rs, 7`) |
* `Zbs` Single-bit instructions: `SBSET[I]` `SBCLR[I]` `SBINV[I]` `SBEXT[I]` |
* `Zbb` base instruction set: `CLZ` `CTZ` `CPOP` `SEXT.B` `SEXT.H` `MIN[U]` `MAX[U]` `ANDN` `ORN` `XNOR` `ROL` `ROR[I]` `zext`(*pseudo-instruction* for `PACK rd, rs, zero`) `rev8`(*pseudo-instruction* for `GREVI rd, rs, -8`) `orc.b`(*pseudo-instruction* for `GORCI rd, rs, 7`) |
* `Zbs` single-bit instructions: `SBSET[I]` `SBCLR[I]` `SBINV[I]` `SBEXT[I]` |
|
|
#### `C` - Compressed instructions extension |
180,14 → 183,22
* ALU instructions: `C.ADDI4SPN` `C.ADD[I]` `C.ADDI16SP` `C.LI` `C.LUI` `C.SLLI` `C.SRLI` `C.SRAI` `C.ANDI` `C.SUB` `C.XOR` `C.OR` `C.AND` `C.MV` `C.NOP` |
* Jump and branch instructions: `C.J` `C.JAL` `C.JR` `C.JALR` `C.BEQZ` `C.BNEZ` |
* Memory instructions: `C.LW` `C.SW` `C.LWSP` `C.SWSP` |
* System instructions: `C.EBREAK` (only with `Zicsr` extension) |
* System instructions: `C.EBREAK` (requires `Zicsr` extension) |
* Floating-point instructions: `C.FLW` `C.FSW` `C.FLWSP` `C.FSWSP` (requires `F` extension) |
* Pseudo-instructions are not listed |
|
#### `E` - Embedded CPU version extension |
|
* Reduced register file (only the 16 lowest registers) |
* Reduced register file (only the 16 lowest registers are implemented) |
|
|
#### `F` - Single-precision floating-point extension |
|
* :construction: **WORK-IN-PROGRESS** :construction: |
* :warning: the `F` extension is not operational yet! |
* :information_source: check out the [F-extension project board](https://github.com/stnolting/neorv32/projects/4) for the current implementation state |
|
|
#### `I` - Base integer instruction set |
|
* ALU instructions: `LUI` `AUIPC` `ADD[I]` `SLT[I][U]` `XOR[I]` `OR[I]` `AND[I]` `SLL[I]` `SRL[I]` `SRA[I]` `SUB` |
227,7 → 238,7
* Pseudo-instructions are not listed |
* Counter CSRs: `[m]cycle[h]` `[m]instret[m]` `time[h]` `[m]hpmcounter*[h]`(3..31, configurable) `mcounteren` `mcountinhibit` `mhpmevent*`(3..31, configurable) |
* Machine CSRs: `mstatus[h]` `misa`(read-only!) `mie` `mtvec` `mscratch` `mepc` `mcause` `mtval` `mip` `mvendorid` [`marchid`](https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md) `mimpid` `mhartid` `mzext`(custom) |
* Supported (sync.) exceptions (all RISC-V-compliant): |
* Supported (sync.) exceptions (implementing the RISC-V specs): |
* Misaligned instruction address |
* Instruction access fault (via timeout/error after unacknowledged bus access) |
* Illegal instruction |
239,9 → 250,9
* Environment call from U-mode (via `ecall` instruction in user mode) |
* Environment call from M-mode (via `ecall` instruction in machine mode) |
* Supported (async.) exceptions / interrupts: |
* Machine timer interrupt `mti` (via processor's MTIME unit / external signal), RISC-V-compliant |
* Machine software interrupt `msi` (via external signal), RISC-V-compliant |
* Machine external interrupt `mei` (via external signal), RISC-V-compliant |
* Machine timer interrupt `mti` (via processor's MTIME unit / external signal) |
* Machine software interrupt `msi` (via external signal) |
* Machine external interrupt `mei` (via external signal) |
* 16 fast interrupt requests (custom extension), 6+1 available for custom usage |
|
|
264,7 → 275,7
* Additional machine CSRs: `mhpmevent*`(3..31) `[m]hpmcounter*[h]`(3..31) |
|
|
### :warning: Non-RISC-V-Compliant Issues and Limitations |
### :warning: Non-RISC-V-Compatible Issues and Limitations |
|
* CPU and Processor are BIG-ENDIAN, but this should be no problem as the external memory bus interface provides big- and little-endian configurations |
* `misa` CSR is read-only - no dynamic enabling/disabling of synthesized CPU extensions during runtime; for compatibility: write accesses (in m-mode) are ignored and do not cause an exception |
271,7 → 282,7
* The physical memory protection (**PMP**) only supports `NAPOT` mode yet and a minimal granularity of 8 bytes |
* The `A` extension only implements `lr.w` and `sc.w` instructions yet. However, these instructions are sufficient to emulate all further AMO operations |
* The `mcause` trap code `0x80000000` (originally reserved in the RISC-V specs) is used to indicate a hardware reset (as "non-maskable interrupt") |
* The bit manipulation extension is not yet officially ratified, but is expected to stay unchanged. There is no software support in the upstream GCC RISC-V port yet. However, an intrinsic library is provided to utilize the provided bit manipulation extension from C-language code (see [`sw/example/bit_manipulation`](https://github.com/stnolting/neorv32/tree/master/sw/example/bit_manipulation)). NEORV32's `B` extension is compliant to spec. version "0.94-draft". |
* The bit manipulation extension is not yet officially ratified, but is expected to stay unchanged. There is no software support in the upstream GCC RISC-V port yet. However, an intrinsic library is provided to utilize the provided bit manipulation extension from C-language code (see [`sw/example/bit_manipulation`](https://github.com/stnolting/neorv32/tree/master/sw/example/bit_manipulation)). NEORV32's `B` extension is compatible to spec. version "0.94-draft". |
|
|
|
304,7 → 315,7
|
### NEORV32 Processor-Internal Peripherals and Memories |
|
Results generated for hardware version [`1.5.1.4`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md). |
Results generated for hardware version [`1.5.2.4`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md). |
|
| Module | Description | LEs | FFs | Memory bits | DSPs | |
|:----------|:-----------------------------------------------------|----:|----:|------------:|-----:| |
317,6 → 328,7
| IMEM | Processor-internal instruction memory (default 16kb) | 6 | 2 | 131 072 | 0 | |
| MTIME | Machine system timer | 274 | 166 | 0 | 0 | |
| NCO | Numerically-controlled oscillator | 254 | 226 | 0 | 0 | |
| NEOLED | Smart LED Interface (NeoPixel-compatibile) [4x FIFO] | 347 | 309 | 0 | 0 | |
| PWM | Pulse-width modulation controller | 71 | 69 | 0 | 0 | |
| SPI | Serial peripheral interface | 138 | 124 | 0 | 0 | |
| SYSINFO | System configuration information memory | 11 | 10 | 0 | 0 | |
669,8 → 681,10
|
"AXI", "AXI4" and "AXI4-Lite" are trademarks of Arm Holdings plc. |
|
"NeoPixel" is a trademark of Adafruit Industries. |
|
|
|
## Acknowledgements |
|
[![RISC-V](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/riscv_logo.png)](https://riscv.org/) |