OpenCores
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/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/)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.