Skip to content

Commit

Permalink
🧪 provide full hardware reset for all FFs (#724)
Browse files Browse the repository at this point in the history
  • Loading branch information
stnolting authored Nov 11, 2023
2 parents 291fe91 + 44dba16 commit 486087e
Show file tree
Hide file tree
Showing 41 changed files with 1,374 additions and 1,222 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 -> Version 01.04.03.12 -> v1.4.3.12

| Date (*dd.mm.yyyy*) | Version | Comment |
|:-------------------:|:-------:|:--------|
| 11.11.2023 | 1.9.0.9 | :test_tube: add full hardware reset for **all** flip flops in CPU/processor; [#724](https://github.com/stnolting/neorv32/pull/724) |
| 09.11.2023 | 1.9.0.8 | minor rtl code cleanups; [#723](https://github.com/stnolting/neorv32/pull/723) |
| 04.11.2023 | 1.9.0.7 | upgrade true random number generator to [neoTRNG version 3](https://github.com/stnolting/neoTRNG); [#721](https://github.com/stnolting/neorv32/pull/721) |
| 31.10.2023 | 1.9.0.6 | update crt0's early-boot trap handler; [#719](https://github.com/stnolting/neorv32/pull/719) |
Expand Down
10 changes: 3 additions & 7 deletions docs/datasheet/soc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -370,13 +370,9 @@ a valid reset of the entire processor. The internal global reset is asserted _ay
`rstn_i` signal. For internal reset sources, the global reset is asserted _synchronously_. If the reset cause gets inactive
the internal reset is de-asserted _synchronously_ at a falling clock edge.

Internally, all processor registers that actually do provide a hardware reset use an **asynchronous reset**. An asynchronous
reset ensures that the entire processor logic is reset to a defined state even if the main clock is not yet operational.

In order to reduce routing constraints (and by this the actual hardware requirements), some _uncritical registers_
of the NEORV32 CPU as well as many registers of the entire NEORV32 Processor do not use a dedicated hardware reset.
For example there are several pipeline registers and "buffer" registers that do not require a defined
initial state to ensure correct operation.
Internally, **all registers** that are not meant for mapping to blockRAM (like the register file) do provide a dedicated and
low-active **asynchronous hardware reset**. This asynchronous reset ensures that the entire processor logic is reset to a
defined state even if the main clock is not operational yet.

[NOTE]
The system reset will only reset the control registers of each implemented IO/peripheral module. This control register
Expand Down
61 changes: 20 additions & 41 deletions rtl/core/mem/neorv32_dmem.default.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -46,40 +46,19 @@ architecture neorv32_dmem_rtl of neorv32_dmem is
signal rden : std_ulogic;
signal addr : std_ulogic_vector(index_size_f(DMEM_SIZE/4)-1 downto 0);

-- -------------------------------------------------------------------------------------------------------------- --
-- The memory (RAM) is built from 4 individual byte-wide memories b0..b3, since some synthesis tools have --
-- problems with 32-bit memories that provide dedicated byte-enable signals AND/OR with multi-dimensional arrays. --
-- [NOTE] Read-during-write behavior is irrelevant as read and write accesses are mutually exclusive. --
-- -------------------------------------------------------------------------------------------------------------- --

-- RAM - not initialized at all --
signal mem_ram_b0 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b1 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b2 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b3 : mem8_t(0 to DMEM_SIZE/4-1);

-- read data --
signal mem_ram_b0_rd, mem_ram_b1_rd, mem_ram_b2_rd, mem_ram_b3_rd : std_ulogic_vector(7 downto 0);
-- The memory (RAM) is built from 4 individual byte-wide memories because some synthesis
-- tools have issues inferring 32-bit memories that provide dedicated byte-enable signals
-- and/or with multi-dimensional arrays. [NOTE] Read-during-write behavior is irrelevant
-- as read and write accesses are mutually exclusive.
signal mem_ram_b0, mem_ram_b1, mem_ram_b2, mem_ram_b3 : mem8_t(0 to DMEM_SIZE/4-1);

begin

-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report
"NEORV32 PROCESSOR CONFIG NOTE: Implementing DEFAULT processor-internal DMEM (RAM, " & natural'image(DMEM_SIZE) &
" bytes)." severity note;


-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
addr <= bus_req_i.addr(index_size_f(DMEM_SIZE/4)+1 downto 2); -- word aligned


-- Memory Access --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_access: process(clk_i)
begin
if rising_edge(clk_i) then
if rising_edge(clk_i) then -- no reset to infer block RAM
if (bus_req_i.stb = '1') and (bus_req_i.rw = '1') then
if (bus_req_i.ben(0) = '1') then -- byte 0
mem_ram_b0(to_integer(unsigned(addr))) <= bus_req_i.data(07 downto 00);
Expand All @@ -94,32 +73,32 @@ begin
mem_ram_b3(to_integer(unsigned(addr))) <= bus_req_i.data(31 downto 24);
end if;
end if;
mem_ram_b0_rd <= mem_ram_b0(to_integer(unsigned(addr)));
mem_ram_b1_rd <= mem_ram_b1(to_integer(unsigned(addr)));
mem_ram_b2_rd <= mem_ram_b2(to_integer(unsigned(addr)));
mem_ram_b3_rd <= mem_ram_b3(to_integer(unsigned(addr)));
rdata(07 downto 00) <= mem_ram_b0(to_integer(unsigned(addr)));
rdata(15 downto 08) <= mem_ram_b1(to_integer(unsigned(addr)));
rdata(23 downto 16) <= mem_ram_b2(to_integer(unsigned(addr)));
rdata(31 downto 24) <= mem_ram_b3(to_integer(unsigned(addr)));
end if;
end process mem_access;

-- word aligned access --
addr <= bus_req_i.addr(index_size_f(DMEM_SIZE/4)+1 downto 2);


-- Bus Feedback ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
bus_feedback: process(clk_i)
bus_feedback: process(rstn_i, clk_i)
begin
if rising_edge(clk_i) then
if (rstn_i = '0') then
rden <= '0';
bus_rsp_o.ack <= '0';
elsif rising_edge(clk_i) then
rden <= bus_req_i.stb and (not bus_req_i.rw);
bus_rsp_o.ack <= bus_req_i.stb;
end if;
end process bus_feedback;

-- pack --
rdata <= mem_ram_b3_rd & mem_ram_b2_rd & mem_ram_b1_rd & mem_ram_b0_rd;

-- output gate --
bus_rsp_o.data <= rdata when (rden = '1') else (others => '0');

-- no access error possible --
bus_rsp_o.err <= '0';
bus_rsp_o.data <= rdata when (rden = '1') else (others => '0'); -- output gate
bus_rsp_o.err <= '0'; -- no access error possible


end neorv32_dmem_rtl;
68 changes: 23 additions & 45 deletions rtl/core/mem/neorv32_dmem.legacy.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -42,45 +42,23 @@ use neorv32.neorv32_package.all;
architecture neorv32_dmem_rtl of neorv32_dmem is

-- local signals --
signal rdata : std_ulogic_vector(31 downto 0);
signal rden : std_ulogic;
signal addr : std_ulogic_vector(index_size_f(DMEM_SIZE/4)-1 downto 0);
signal addr_ff : std_ulogic_vector(index_size_f(DMEM_SIZE/4)-1 downto 0);
signal rdata : std_ulogic_vector(31 downto 0);
signal rden : std_ulogic;
signal addr, addr_ff : std_ulogic_vector(index_size_f(DMEM_SIZE/4)-1 downto 0);

-- -------------------------------------------------------------------------------------------------------------- --
-- The memory (RAM) is built from 4 individual byte-wide memories b0..b3, since some synthesis tools have --
-- problems with 32-bit memories that provide dedicated byte-enable signals AND/OR with multi-dimensional arrays. --
-- [NOTE] Read-during-write behavior is irrelevant as read and write accesses are mutually exclusive. --
-- -------------------------------------------------------------------------------------------------------------- --

-- RAM - not initialized at all --
signal mem_ram_b0 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b1 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b2 : mem8_t(0 to DMEM_SIZE/4-1);
signal mem_ram_b3 : mem8_t(0 to DMEM_SIZE/4-1);

-- read data --
signal mem_ram_b0_rd, mem_ram_b1_rd, mem_ram_b2_rd, mem_ram_b3_rd : std_ulogic_vector(7 downto 0);
-- The memory (RAM) is built from 4 individual byte-wide memories because some synthesis
-- tools have issues inferring 32-bit memories that provide dedicated byte-enable signals
-- and/or with multi-dimensional arrays. [NOTE] Read-during-write behavior is irrelevant
-- as read and write accesses are mutually exclusive.
signal mem_ram_b0, mem_ram_b1, mem_ram_b2, mem_ram_b3 : mem8_t(0 to DMEM_SIZE/4-1);

begin

-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert false report
"NEORV32 PROCESSOR CONFIG NOTE: Implementing LEGACY processor-internal DMEM (RAM, " & natural'image(DMEM_SIZE) &
" bytes)." severity note;


-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
addr <= bus_req_i.addr(index_size_f(DMEM_SIZE/4)+1 downto 2); -- word aligned


-- Memory Access --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_access: process(clk_i)
begin
if rising_edge(clk_i) then
if rising_edge(clk_i) then -- no reset to infer block RAM
addr_ff <= addr;
if (bus_req_i.stb = '1') and (bus_req_i.rw = '1') then
if (bus_req_i.ben(0) = '1') then -- byte 0
Expand All @@ -100,30 +78,30 @@ begin
end process mem_access;

-- sync(!) read - alternative HDL style --
mem_ram_b0_rd <= mem_ram_b0(to_integer(unsigned(addr_ff)));
mem_ram_b1_rd <= mem_ram_b1(to_integer(unsigned(addr_ff)));
mem_ram_b2_rd <= mem_ram_b2(to_integer(unsigned(addr_ff)));
mem_ram_b3_rd <= mem_ram_b3(to_integer(unsigned(addr_ff)));
rdata(07 downto 00) <= mem_ram_b0(to_integer(unsigned(addr_ff)));
rdata(15 downto 08) <= mem_ram_b1(to_integer(unsigned(addr_ff)));
rdata(23 downto 16) <= mem_ram_b2(to_integer(unsigned(addr_ff)));
rdata(31 downto 24) <= mem_ram_b3(to_integer(unsigned(addr_ff)));

-- word aligned access --
addr <= bus_req_i.addr(index_size_f(DMEM_SIZE/4)+1 downto 2);


-- Bus Feedback ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
bus_feedback: process(clk_i)
bus_feedback: process(rstn_i, clk_i)
begin
if rising_edge(clk_i) then
if (rstn_i = '0') then
rden <= '0';
bus_rsp_o.ack <= '0';
elsif rising_edge(clk_i) then
rden <= bus_req_i.stb and (not bus_req_i.rw);
bus_rsp_o.ack <= bus_req_i.stb;
end if;
end process bus_feedback;

-- pack --
rdata <= mem_ram_b3_rd & mem_ram_b2_rd & mem_ram_b1_rd & mem_ram_b0_rd;

-- output gate --
bus_rsp_o.data <= rdata when (rden = '1') else (others => '0');

-- no access error possible --
bus_rsp_o.err <= '0';
bus_rsp_o.data <= rdata when (rden = '1') else (others => '0'); -- output gate
bus_rsp_o.err <= '0'; -- no access error possible


end neorv32_dmem_rtl;
74 changes: 26 additions & 48 deletions rtl/core/mem/neorv32_imem.default.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -58,70 +58,50 @@ architecture neorv32_imem_rtl of neorv32_imem is
constant imem_app_size_c : natural := (application_init_image'length)*4;

-- ROM - initialized with executable code --
constant mem_rom : mem32_t(0 to IMEM_SIZE/4-1) := mem32_init_f(application_init_image, IMEM_SIZE/4);
constant mem_rom_c : mem32_t(0 to IMEM_SIZE/4-1) := mem32_init_f(application_init_image, IMEM_SIZE/4);

-- read data --
signal mem_rom_rd : std_ulogic_vector(31 downto 0);

-- -------------------------------------------------------------------------------------------------------------- --
-- The memory (RAM) is built from 4 individual byte-wide memories b0..b3, since some synthesis tools have --
-- problems with 32-bit memories that provide dedicated byte-enable signals AND/OR with multi-dimensional arrays. --
-- [NOTE] Read-during-write behavior is irrelevant as read and write accesses are mutually exclusive. --
-- -------------------------------------------------------------------------------------------------------------- --

-- RAM - not initialized at all --
signal mem_ram_b0 : mem8_t(0 to IMEM_SIZE/4-1);
signal mem_ram_b1 : mem8_t(0 to IMEM_SIZE/4-1);
signal mem_ram_b2 : mem8_t(0 to IMEM_SIZE/4-1);
signal mem_ram_b3 : mem8_t(0 to IMEM_SIZE/4-1);

-- read data --
signal mem_b0_rd, mem_b1_rd, mem_b2_rd, mem_b3_rd : std_ulogic_vector(7 downto 0);
-- The memory (RAM) is built from 4 individual byte-wide memories because some synthesis
-- tools have issues inferring 32-bit memories that provide dedicated byte-enable signals
-- and/or with multi-dimensional arrays. [NOTE] Read-during-write behavior is irrelevant
-- as read and write accesses are mutually exclusive.
signal mem_ram_b0, mem_ram_b1, mem_ram_b2, mem_ram_b3 : mem8_t(0 to IMEM_SIZE/4-1);

begin

-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (IMEM_AS_IROM = true) report
"NEORV32 PROCESSOR CONFIG NOTE: Implementing DEFAULT processor-internal IMEM as ROM (" & natural'image(IMEM_SIZE) &
" bytes), pre-initialized with application (" & natural'image(imem_app_size_c) & " bytes)." severity note;

assert not (IMEM_AS_IROM = false) report
"NEORV32 PROCESSOR CONFIG NOTE: Implementing processor-internal IMEM as blank RAM (" & natural'image(IMEM_SIZE) &
" bytes)." severity note;
assert false report
"NEORV32 PROCESSOR CONFIG NOTE: Implementing DEFAULT processor-internal IMEM as " &
cond_sel_string_f(IMEM_AS_IROM, "pre-initialized ROM.", "blank RAM.") severity note;

assert not ((IMEM_AS_IROM = true) and (imem_app_size_c > IMEM_SIZE)) report
"NEORV32 PROCESSOR CONFIG ERROR: Application (image = " & natural'image(imem_app_size_c) &
" bytes) does not fit into processor-internal IMEM (ROM = " & natural'image(IMEM_SIZE) & " bytes)!" severity error;


-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
addr <= bus_req_i.addr(index_size_f(IMEM_SIZE/4)+1 downto 2); -- word aligned


-- Implement IMEM as pre-initialized ROM --------------------------------------------------
-- -------------------------------------------------------------------------------------------
imem_rom:
if (IMEM_AS_IROM = true) generate
mem_access: process(clk_i)
begin
if rising_edge(clk_i) then
mem_rom_rd <= mem_rom(to_integer(unsigned(addr)));
if rising_edge(clk_i) then -- no reset to infer block RAM
rdata <= mem_rom_c(to_integer(unsigned(addr)));
end if;
end process mem_access;
-- read data --
rdata <= mem_rom_rd;
end generate;

-- word aligned access --
addr <= bus_req_i.addr(index_size_f(IMEM_SIZE/4)+1 downto 2);


-- Implement IMEM as non-initialized RAM --------------------------------------------------
-- -------------------------------------------------------------------------------------------
imem_ram:
if (IMEM_AS_IROM = false) generate
mem_access: process(clk_i)
begin
if rising_edge(clk_i) then
if rising_edge(clk_i) then -- no reset to infer block RAM
if (bus_req_i.stb = '1') and (bus_req_i.rw = '1') then
if (bus_req_i.ben(0) = '1') then -- byte 0
mem_ram_b0(to_integer(unsigned(addr))) <= bus_req_i.data(07 downto 00);
Expand All @@ -136,22 +116,23 @@ begin
mem_ram_b3(to_integer(unsigned(addr))) <= bus_req_i.data(31 downto 24);
end if;
end if;
mem_b0_rd <= mem_ram_b0(to_integer(unsigned(addr)));
mem_b1_rd <= mem_ram_b1(to_integer(unsigned(addr)));
mem_b2_rd <= mem_ram_b2(to_integer(unsigned(addr)));
mem_b3_rd <= mem_ram_b3(to_integer(unsigned(addr)));
rdata(07 downto 00) <= mem_ram_b0(to_integer(unsigned(addr)));
rdata(15 downto 08) <= mem_ram_b1(to_integer(unsigned(addr)));
rdata(23 downto 16) <= mem_ram_b2(to_integer(unsigned(addr)));
rdata(31 downto 24) <= mem_ram_b3(to_integer(unsigned(addr)));
end if;
end process mem_access;
-- read data --
rdata <= mem_b3_rd & mem_b2_rd & mem_b1_rd & mem_b0_rd;
end generate;


-- Bus Feedback ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
bus_feedback: process(clk_i)
bus_feedback: process(rstn_i, clk_i)
begin
if rising_edge(clk_i) then
if (rstn_i = '0') then
rden <= '0';
bus_rsp_o.ack <= '0';
elsif rising_edge(clk_i) then
rden <= bus_req_i.stb and (not bus_req_i.rw);
if (IMEM_AS_IROM = true) then
bus_rsp_o.ack <= bus_req_i.stb and (not bus_req_i.rw); -- read-only!
Expand All @@ -161,11 +142,8 @@ begin
end if;
end process bus_feedback;

-- output gate --
bus_rsp_o.data <= rdata when (rden = '1') else (others => '0');

-- no access error possible --
bus_rsp_o.err <= '0';
bus_rsp_o.data <= rdata when (rden = '1') else (others => '0'); -- output gate
bus_rsp_o.err <= '0'; -- no access error possible


end neorv32_imem_rtl;
Loading

0 comments on commit 486087e

Please sign in to comment.