Skip to content

Commit

Permalink
Merge pull request #405 from stnolting/reset_cleanup
Browse files Browse the repository at this point in the history
[rtl] Cleanup hardware reset logic
  • Loading branch information
stnolting authored Sep 3, 2022
2 parents a86ec1e + 6f1e5df commit 16485e9
Show file tree
Hide file tree
Showing 17 changed files with 123 additions and 246 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ mimpid = 0x01040312 => 01.04.03.12 => Version 01.04.03.12 => v1.4.3.12

| Date (*dd.mm.yyyy*) | Version | Comment |
|:-------------------:|:-------:|:--------|
| 03.09.2022 | 1.7.6.2 | cleanup hardware reset logic; [#405](https://github.com/stnolting/neorv32/pull/405) |
| 02.09.2022 | 1.7.6.1 | :sparkles: add new processor module: **1-Wire Interface Controller** (ONEWIRE); [#402](https://github.com/stnolting/neorv32/pull/402) |
| 28.08.2022 | [**:rocket:1.7.6**](https://github.com/stnolting/neorv32/releases/tag/v1.7.6) | **New release** |
| 27.08.2022 | 1.7.5.9 | fix minor core rtl issues that were found while experimenting with a low-level netlist of the processor; [#398](https://github.com/stnolting/neorv32/pull/398) |
Expand Down
42 changes: 8 additions & 34 deletions docs/datasheet/cpu.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1083,43 +1083,17 @@ memory system to perform the necessary operations (for example a cache flush/rel
:sectnums:
==== CPU Hardware Reset

In order to reduce routing constraints (and by this the actual hardware requirements), most uncritical
registers of the NEORV32 CPU as well as most register of the whole NEORV32 Processor do not use **a
dedicated hardware reset**. "Uncritical registers" in this context means that the initial value of these registers
after power-up/reset is not relevant for a defined CPU boot process.
In order to reduce routing constraints (and by this the actual hardware requirements), most _uncritical registers_
of the NEORV32 CPU as well as most registers of the whole NEORV32 Processor do not use **a dedicated hardware reset**.
"Uncritical registers" in this context means that the initial value of the according register(s)
after power-up/reset is not relevant for a defined CPU boot/start process.


**Rationale**

A good example to illustrate the concept of uncritical registers is a pipelined processing engine. Each stage
of the engine features an N-bit _data register_ and a 1-bit _status register_. The status register is set when the
data in the according data register is valid. At the end of the pipeline the status register might trigger a write-back
of the processing result to some kind of memory. The initial status of the data registers after power-up is
irrelevant as long as the status registers are all reset to a defined value that indicates there is no valid data in
the pipeline's data register. Therefore, the pipeline data register do no require a dedicated reset as they do not
control the actual operation (in contrast to the status register). This makes the pipeline data registers from
this example "uncritical registers".


**NEORV32 CPU Reset**
Many CPU-internal register do provide an asynchronous reset described in the VHDL code, but the "don't care" value
(VHDL `'-'`) is used for initialization of uncritical registers - effectively generating a flip-flop without a
reset input.

In terms of the NEORV32 CPU, there are several pipeline registers, state machine registers and even some status
and control registers (CSRs) that do not require a defined initial state to ensure a correct boot process. The
pipeline register will get initialized by the CPU's internal state machines, which are initialized from the main
control engine that actually features a defined reset.


**Reset Configuration**

Most CPU-internal register do provide an asynchronous reset in the VHDL code, but the "don't care" value
(VHDL `'-'`) is used for initialization of all uncritical registers - effectively generating a flip-flop without a
reset. However, certain applications or situations (like advanced gate-level / timing simulations) might
require a more deterministic reset state. For this case, a defined reset level (reset-to-low) of most CPU registers can
be configured by enabling a constant in the main VHDL package file (`rtl/core/neorv32_package.vhd`):
control engine that actually features a defined hardware reset.

[source,vhdl]
----
-- use dedicated hardware reset value for UNCRITICAL registers --
-- FALSE=reset value is irrelevant (might simplify HW), default; TRUE=defined LOW reset value
constant dedicated_reset_c : boolean := false;
----
8 changes: 6 additions & 2 deletions docs/datasheet/cpu_csr.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,11 @@ the <<_mxisa>> CSR. +
If _CPU_CNT_WIDTH_ is 0, the <<_cycleh>> and <<_instreth>> / <<_mcycleh>> and <<_minstreth>> CSRs are hardwired to zero
and any write access to them is ignored.
.Counter Reset
[IMPORTANT]
The counter CSRs do **not** provide a hardware reset. Hence, the CSRs have to be explicitly initialized by software
before being used.
:sectnums!:
===== **`cycle[h]`**
Expand Down Expand Up @@ -842,8 +847,7 @@ NEORV32-specific read-only CSR that helps machine-mode software to discover `Z*`
| Bit | Name [C] | R/W | Function
| 31 | _CSR_MXISA_FASTSHIFT_ | r/- | fast shifts available when set (via top's <<_fast_shift_en>> generic)
| 30 | _CSR_MXISA_FASTMUL_ | r/- | fast multiplication available when set (via top's <<_fast_mul_en>> generic)
| 31:22 | - | r/- | _reserved_, read as zero
| 21 | _CSR_MXISA_HW_RESET_ | r/- | set if a dedicated hardware reset of all core registers is implemented (via package's `dedicated_reset_c` constant)
| 31:21 | - | r/- | _reserved_, read as zero
| 20 | _CSR_MXISA_IS_SIM_ | r/- | set if CPU is being **simulated** (⚠️ not guaranteed)
| 19:11 | - | r/- | _reserved_, read as zero
| 10 | _CSR_MXISA_DEBUGMODE_ | r/- | RISC-V CPU `debug_mode` available when set (via top's <<_on_chip_debugger_en>> generic)
Expand Down
51 changes: 26 additions & 25 deletions docs/datasheet/soc_sysinfo.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -51,31 +51,32 @@ will signal a "DEVICE ERROR" in this case.
[options="header",grid="all"]
|=======================
| Bit | Name [C] | Function
| `0` | _SYSINFO_SOC_BOOTLOADER_ | set if the processor-internal bootloader is implemented (via top's <<_int_bootloader_en>> generic)
| `1` | _SYSINFO_SOC_MEM_EXT_ | set if the external Wishbone bus interface is implemented (via top's <<_mem_ext_en>> generic)
| `2` | _SYSINFO_SOC_MEM_INT_IMEM_ | set if the processor-internal DMEM implemented (via top's <<_mem_int_dmem_en>> generic)
| `3` | _SYSINFO_SOC_MEM_INT_DMEM_ | set if the processor-internal IMEM is implemented (via top's <<_mem_int_imem_en>> generic)
| `4` | _SYSINFO_SOC_MEM_EXT_ENDIAN_ | set if external bus interface uses BIG-endian byte-order (via top's <<_mem_ext_big_endian>> generic)
| `5` | _SYSINFO_SOC_ICACHE_ | set if processor-internal instruction cache is implemented (via top's <<_icache_en>> generic)
| `13` | _SYSINFO_SOC_IS_SIM_ | set if processor is being **simulated** (⚠️ not guaranteed)
| `14` | _SYSINFO_SOC_OCD_ | set if on-chip debugger implemented (via top's <<_on_chip_debugger_en>> generic)
| `15` | _SYSINFO_SOC_HW_RESET_ | set if a dedicated hardware reset of all core registers is implemented (via package's `dedicated_reset_c` constant)
| `16` | _SYSINFO_SOC_IO_GPIO_ | set if the GPIO is implemented (via top's <<_io_gpio_en>> generic)
| `17` | _SYSINFO_SOC_IO_MTIME_ | set if the MTIME is implemented (via top's <<_io_mtime_en>> generic)
| `18` | _SYSINFO_SOC_IO_UART0_ | set if the primary UART0 is implemented (via top's <<_io_uart0_en>> generic)
| `19` | _SYSINFO_SOC_IO_SPI_ | set if the SPI is implemented (via top's <<_io_spi_en>> generic)
| `20` | _SYSINFO_SOC_IO_TWI_ | set if the TWI is implemented (via top's <<_io_twi_en>> generic)
| `21` | _SYSINFO_SOC_IO_PWM_ | set if the PWM is implemented (via top's <<_io_pwm_num_ch>> generic)
| `22` | _SYSINFO_SOC_IO_WDT_ | set if the WDT is implemented (via top's <<_io_wdt_en>> generic)
| `23` | _SYSINFO_SOC_IO_CFS_ | set if the custom functions subsystem is implemented (via top's <<_io_cfs_en>> generic)
| `24` | _SYSINFO_SOC_IO_TRNG_ | set if the TRNG is implemented (via top's _IO_TRNG_EN_ generic)
| `25` | _SYSINFO_SOC_IO_SLINK_ | set if the SLINK is implemented (via top's <<_slink_num_tx>> and/or <<_slink_num_rx>> generics)
| `26` | _SYSINFO_SOC_IO_UART1_ | set if the secondary UART1 is implemented (via top's <<_io_uart1_en>> generic)
| `27` | _SYSINFO_SOC_IO_NEOLED_ | set if the NEOLED is implemented (via top's <<_io_neoled_en>> generic)
| `28` | _SYSINFO_SOC_IO_XIRQ_ | set if the XIRQ is implemented (via top's <<_xirq_num_ch>> generic)
| `29` | _SYSINFO_SOC_IO_GPTMR_ | set if the GPTMR is implemented (via top's <<_io_gptmr_en>> generic)
| `30` | _SYSINFO_SOC_IO_XIP_ | set if the XIP module is implemented (via top's <<_io_xip_en>> generic)
| `31` | _SYSINFO_SOC_IO_ONEWIRE_ | set if the ONEWIRE interface is implemented (via top's <<_io_onewire_en>> generic)
| `0` | _SYSINFO_SOC_BOOTLOADER_ | set if the processor-internal bootloader is implemented (via top's <<_int_bootloader_en>> generic)
| `1` | _SYSINFO_SOC_MEM_EXT_ | set if the external Wishbone bus interface is implemented (via top's <<_mem_ext_en>> generic)
| `2` | _SYSINFO_SOC_MEM_INT_IMEM_ | set if the processor-internal DMEM implemented (via top's <<_mem_int_dmem_en>> generic)
| `3` | _SYSINFO_SOC_MEM_INT_DMEM_ | set if the processor-internal IMEM is implemented (via top's <<_mem_int_imem_en>> generic)
| `4` | _SYSINFO_SOC_MEM_EXT_ENDIAN_ | set if external bus interface uses BIG-endian byte-order (via top's <<_mem_ext_big_endian>> generic)
| `5` | _SYSINFO_SOC_ICACHE_ | set if processor-internal instruction cache is implemented (via top's <<_icache_en>> generic)
| `12:6` | - | _reserved_, read as zero
| `13` | _SYSINFO_SOC_IS_SIM_ | set if processor is being **simulated** (⚠️ not guaranteed)
| `14` | _SYSINFO_SOC_OCD_ | set if on-chip debugger implemented (via top's <<_on_chip_debugger_en>> generic)
| `15` | - | _reserved_, read as zero
| `16` | _SYSINFO_SOC_IO_GPIO_ | set if the GPIO is implemented (via top's <<_io_gpio_en>> generic)
| `17` | _SYSINFO_SOC_IO_MTIME_ | set if the MTIME is implemented (via top's <<_io_mtime_en>> generic)
| `18` | _SYSINFO_SOC_IO_UART0_ | set if the primary UART0 is implemented (via top's <<_io_uart0_en>> generic)
| `19` | _SYSINFO_SOC_IO_SPI_ | set if the SPI is implemented (via top's <<_io_spi_en>> generic)
| `20` | _SYSINFO_SOC_IO_TWI_ | set if the TWI is implemented (via top's <<_io_twi_en>> generic)
| `21` | _SYSINFO_SOC_IO_PWM_ | set if the PWM is implemented (via top's <<_io_pwm_num_ch>> generic)
| `22` | _SYSINFO_SOC_IO_WDT_ | set if the WDT is implemented (via top's <<_io_wdt_en>> generic)
| `23` | _SYSINFO_SOC_IO_CFS_ | set if the custom functions subsystem is implemented (via top's <<_io_cfs_en>> generic)
| `24` | _SYSINFO_SOC_IO_TRNG_ | set if the TRNG is implemented (via top's _IO_TRNG_EN_ generic)
| `25` | _SYSINFO_SOC_IO_SLINK_ | set if the SLINK is implemented (via top's <<_slink_num_tx>> and/or <<_slink_num_rx>> generics)
| `26` | _SYSINFO_SOC_IO_UART1_ | set if the secondary UART1 is implemented (via top's <<_io_uart1_en>> generic)
| `27` | _SYSINFO_SOC_IO_NEOLED_ | set if the NEOLED is implemented (via top's <<_io_neoled_en>> generic)
| `28` | _SYSINFO_SOC_IO_XIRQ_ | set if the XIRQ is implemented (via top's <<_xirq_num_ch>> generic)
| `29` | _SYSINFO_SOC_IO_GPTMR_ | set if the GPTMR is implemented (via top's <<_io_gptmr_en>> generic)
| `30` | _SYSINFO_SOC_IO_XIP_ | set if the XIP module is implemented (via top's <<_io_xip_en>> generic)
| `31` | _SYSINFO_SOC_IO_ONEWIRE_ | set if the ONEWIRE interface is implemented (via top's <<_io_onewire_en>> generic)
|=======================


Expand Down
1 change: 0 additions & 1 deletion docs/userguide/simulating_the_processor.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ Using simulation runtime args: --stop-time=10ms <5>
../rtl/core/neorv32_top.vhd:370:3:@0ms:(assertion note): NEORV32 PROCESSOR CONFIG NOTE: Boot configuration: Direct boot from memory (processor-internal IMEM).
../rtl/core/neorv32_top.vhd:394:3:@0ms:(assertion note): NEORV32 PROCESSOR CONFIG NOTE: Implementing on-chip debugger (OCD).
../rtl/core/neorv32_cpu.vhd:169:3:@0ms:(assertion note): NEORV32 CPU ISA Configuration (MARCH): RV32IMCU_Zbb_Zicsr_Zifencei_Zfinx_Debug
../rtl/core/neorv32_cpu.vhd:189:3:@0ms:(assertion note): NEORV32 CPU CONFIG NOTE: Implementing NO dedicated hardware reset for uncritical registers (default, might reduce area). Set package constant <dedicated_reset_c> = TRUE to configure a DEFINED reset value for all CPU registers.
../rtl/core/neorv32_imem.vhd:107:3:@0ms:(assertion note): NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as ROM (16384 bytes), pre-initialized with application (4612 bytes).
../rtl/core/neorv32_dmem.vhd:89:3:@0ms:(assertion note): NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal DMEM (RAM, 8192 bytes).
../rtl/core/neorv32_wishbone.vhd:136:3:@0ms:(assertion note): NEORV32 PROCESSOR CONFIG NOTE: External Bus Interface - Implementing STANDARD Wishbone protocol.
Expand Down
20 changes: 0 additions & 20 deletions rtl/core/neorv32_cpu.vhd
Original file line number Diff line number Diff line change
@@ -1,21 +1,6 @@
-- #################################################################################################
-- # << NEORV32 - CPU Top Entity >> #
-- # ********************************************************************************************* #
-- # NEORV32 CPU: #
-- # * neorv32_cpu.vhd - CPU top entity #
-- # * neorv32_cpu_alu.vhd - Arithmetic/logic unit #
-- # * neorv32_cpu_cp_bitmanip.vhd - Bit-manipulation co-processor #
-- # * neorv32_cpu_cp_cfu.vhd - Custom instructions co-processor #
-- # * neorv32_cpu_cp_fpu.vhd - Single-precision FPU co-processor #
-- # * neorv32_cpu_cp_muldiv.vhd - Integer multiplier/divider co-processor #
-- # * neorv32_cpu_cp_shifter.vhd - Base ISA shifter unit #
-- # * neorv32_cpu_bus.vhd - Load/store unit & physical memory protection #
-- # * neorv32_cpu_control.vhd - CPU control and CSR system #
-- # * neorv32_cpu_decompressor.vhd - Compressed instructions decoder #
-- # * neorv32_fifo.vhd - Instruction prefetch buffer #
-- # * neorv32_cpu_regfile.vhd - Data register file #
-- # * neorv32_package.vhd - Main CPU & Processor package file #
-- # #
-- # Check out the CPU's online documentation for more information: #
-- # HQ: https://github.com/stnolting/neorv32 #
-- # Data Sheet: https://stnolting.github.io/neorv32 #
Expand Down Expand Up @@ -189,11 +174,6 @@ begin
assert not (is_simulation_c = true) report "NEORV32 CPU WARNING! Assuming this is a simulation." severity warning;
assert not (is_simulation_c = false) report "NEORV32 CPU NOTE: Assuming this is real hardware." severity note;

-- hardware reset notifier --
assert not (dedicated_reset_c = false) report "NEORV32 CPU CONFIG NOTE: Implementing NO dedicated hardware reset for uncritical registers (default)." severity note;
assert not (dedicated_reset_c = true) report "NEORV32 CPU CONFIG NOTE: Implementing defined hardware reset for uncritical registers (non-default, reset-to-zero, might increase area)." severity note;
assert not ((def_rst_val_c /= '-') and (def_rst_val_c /= '0')) report "NEORV32 CPU CONFIG ERROR! Invalid configuration of package <def_rst_val_c> constant (has to be '-' or '0')." severity error;

-- CPU boot address --
assert not (CPU_BOOT_ADDR(1 downto 0) /= "00") report "NEORV32 CPU CONFIG ERROR! <CPU_BOOT_ADDR> has to be 32-bit aligned." severity error;
assert false report "NEORV32 CPU CONFIG NOTE: Boot from address 0x" & to_hstring32_f(CPU_BOOT_ADDR) & "." severity note;
Expand Down
15 changes: 5 additions & 10 deletions rtl/core/neorv32_cpu_bus.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ begin
mem_adr_reg: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
mar <= (others => def_rst_val_c);
mar <= (others => '0');
misaligned <= '0';
elsif rising_edge(clk_i) then
if (ctrl_i(ctrl_bus_mo_we_c) = '1') then
Expand All @@ -158,12 +158,9 @@ begin

-- Write Data -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_do_reg: process(rstn_i, clk_i)
mem_do_reg: process(clk_i)
begin
if (rstn_i = '0') then
d_bus_wdata_o <= (others => def_rst_val_c);
d_bus_ben_o <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
if rising_edge(clk_i) then
if (ctrl_i(ctrl_bus_mo_we_c) = '1') then
-- byte enable and data alignment --
case ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) is -- data size
Expand Down Expand Up @@ -197,11 +194,9 @@ begin

-- Read Data ------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
read_align: process(rstn_i, clk_i)
read_align: process(clk_i)
begin
if (rstn_i = '0') then
rdata_o <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
if rising_edge(clk_i) then
-- input data alignment and sign extension --
case ctrl_i(ctrl_ir_funct3_1_c downto ctrl_ir_funct3_0_c) is
when "00" => -- byte
Expand Down
18 changes: 4 additions & 14 deletions rtl/core/neorv32_cpu_control.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -1747,7 +1747,7 @@ begin
csr.mip_firq_nclr <= (others => '-');
--
csr.pmpcfg <= (others => (others => '0'));
csr.pmpaddr <= (others => (others => def_rst_val_c));
csr.pmpaddr <= (others => (others => '-'));
--
csr.mhpmevent <= (others => (others => '0'));
--
Expand Down Expand Up @@ -2358,7 +2358,6 @@ begin
csr.rdata(10) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG); -- RISC-V debug mode
-- misc --
csr.rdata(20) <= bool_to_ulogic_f(is_simulation_c); -- is this a simulation?
csr.rdata(21) <= bool_to_ulogic_f(dedicated_reset_c); -- dedicated hardware reset of all core registers?
-- tuning options --
csr.rdata(30) <= bool_to_ulogic_f(FAST_MUL_EN); -- DSP-based multiplication (M extensions only)
csr.rdata(31) <= bool_to_ulogic_f(FAST_SHIFT_EN); -- parallel logic for shifts (barrel shifters)
Expand All @@ -2383,19 +2382,10 @@ begin

-- Control and Status Registers - Counters ------------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_counters: process(rstn_i, clk_i)
csr_counters: process(clk_i)
begin
if (rstn_i = '0') then
csr.mcycle <= (others => def_rst_val_c);
csr.mcycle_ovfl <= (others => def_rst_val_c);
csr.mcycleh <= (others => def_rst_val_c);
csr.minstret <= (others => def_rst_val_c);
csr.minstret_ovfl <= (others => def_rst_val_c);
csr.minstreth <= (others => def_rst_val_c);
csr.mhpmcounter <= (others => (others => def_rst_val_c));
csr.mhpmcounter_ovfl <= (others => (others => def_rst_val_c));
csr.mhpmcounterh <= (others => (others => def_rst_val_c));
elsif rising_edge(clk_i) then
-- NOTE: the counter CSRs do NOT have a dedicated reset and need to be initialized by software before being used!
if rising_edge(clk_i) then

-- [m]cycle --
if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
Expand Down
Loading

0 comments on commit 16485e9

Please sign in to comment.