diff --git a/CHANGELOG.md b/CHANGELOG.md index 4be7712ed..4703ba996 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12 | Date | Version | Comment | Link | |:----:|:-------:|:--------|:----:| +| 23.02.2024 | 1.9.5.8 | optimize FIFO component to improve technology mapping (inferring blockRAM for "async read" configuration); :bug: fix SLINK status flag delay | [#828](https://github.com/stnolting/neorv32/pull/828) | | 23.02.2024 | 1.9.5.7 | fix FIFO synthesis issue (Vivado cannot infer block RAM nor LUT-RAM) | [#827](https://github.com/stnolting/neorv32/pull/827) | | 20.02.2024 | 1.9.5.6 | :bug: fix bug in `mip.firq` CSR access; `mip.firq` bits are now read-write - software can trigger FIRQs by writing `1` to the according CSR bit | [#821](https://github.com/stnolting/neorv32/pull/821) | | 19.02.2024 | 1.9.5.5 | SLINK: add native hardware support for AXI-stream's "tlast" signal | [#815](https://github.com/stnolting/neorv32/pull/815) | diff --git a/rtl/core/neorv32_fifo.vhd b/rtl/core/neorv32_fifo.vhd index f4c692e5a..a0b263444 100644 --- a/rtl/core/neorv32_fifo.vhd +++ b/rtl/core/neorv32_fifo.vhd @@ -76,6 +76,10 @@ architecture neorv32_fifo_rtl of neorv32_fifo is -- FIFO control -- signal we, re : std_ulogic; -- write-/read-enable signal w_pnt, r_pnt : std_ulogic_vector(index_size_f(fifo_depth_c) downto 0); -- write/read pointer + signal w_nxt, r_nxt : std_ulogic_vector(index_size_f(fifo_depth_c) downto 0); + + -- read access pointer register for async. read -- + signal r_pnt_ff : std_ulogic_vector(index_size_f(fifo_depth_c) downto 0); -- status -- signal match, empty, full, half, free, avail : std_ulogic; @@ -99,21 +103,19 @@ begin w_pnt <= (others => '0'); r_pnt <= (others => '0'); elsif rising_edge(clk_i) then - -- write port -- - if (clear_i = '1') then - w_pnt <= (others => '0'); - elsif (we = '1') then - w_pnt <= std_ulogic_vector(unsigned(w_pnt) + 1); - end if; - -- read port -- - if (clear_i = '1') then - r_pnt <= (others => '0'); - elsif (re = '1') then - r_pnt <= std_ulogic_vector(unsigned(r_pnt) + 1); - end if; + w_pnt <= w_nxt; + r_pnt <= r_nxt; end if; end process pointer_update; + -- async pointer update -- + w_nxt <= (others => '0') when (clear_i = '1') else std_ulogic_vector(unsigned(w_pnt) + 1) when (we = '1') else w_pnt; + r_nxt <= (others => '0') when (clear_i = '1') else std_ulogic_vector(unsigned(r_pnt) + 1) when (re = '1') else r_pnt; + + + -- Status --------------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + -- more than 1 FIFO entries -- check_large: if (fifo_depth_c > 1) generate @@ -137,68 +139,137 @@ begin avail <= not empty; - -- Write Access --------------------------------------------------------------------------- + -- Write Access (with Reset) -------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - memory_full_reset: -- cannot be mapped to block RAM! + memory_full_reset: -- cannot be mapped to memory primitives if FULL_RESET generate - fifo_write_rst: process(rstn_i, clk_i) - begin - if (rstn_i = '0') then - fifo_mem <= (others => (others => '0')); - fifo_reg <= (others => '0'); - elsif rising_edge(clk_i) then - if (we = '1') then - if (fifo_depth_c > 1) then - fifo_mem(to_integer(unsigned(w_pnt(w_pnt'left-1 downto 0)))) <= wdata_i; - else + + -- just 1 FIFO entry -- + fifo_write_reset_small: + if (fifo_depth_c = 1) generate + write_reset_small: process(rstn_i, clk_i) + begin + if (rstn_i = '0') then + fifo_reg <= (others => '0'); + elsif rising_edge(clk_i) then + if (we = '1') then fifo_reg <= wdata_i; end if; end if; - end if; - end process fifo_write_rst; + end process write_reset_small; + end generate; + + -- more than 1 FIFO entries -- + fifo_write_reset_large: + if (fifo_depth_c > 1) generate + write_reset_large: process(rstn_i, clk_i) + begin + if (rstn_i = '0') then + fifo_mem <= (others => (others => '0')); + elsif rising_edge(clk_i) then + if (we = '1') then + fifo_mem(to_integer(unsigned(w_pnt(w_pnt'left-1 downto 0)))) <= wdata_i; + end if; + end if; + end process write_reset_large; + end generate; + end generate; - memory_no_reset: -- no reset to infer block RAM + + -- Write Access (without Reset) ----------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + memory_no_reset: -- no reset to infer memory primitives if not FULL_RESET generate - fifo_write: process(clk_i) - begin - if rising_edge(clk_i) then - if (we = '1') then - if (fifo_depth_c > 1) then - fifo_mem(to_integer(unsigned(w_pnt(w_pnt'left-1 downto 0)))) <= wdata_i; - else + + -- just 1 FIFO entry -- + fifo_write_noreset_small: + if (fifo_depth_c = 1) generate + write_small: process(clk_i) + begin + if rising_edge(clk_i) then + if (we = '1') then fifo_reg <= wdata_i; end if; end if; - end if; - end process fifo_write; + end process write_small; + end generate; + + -- more than 1 FIFO entries -- + fifo_write_noreset_large: + if (fifo_depth_c > 1) generate + write_large: process(clk_i) + begin + if rising_edge(clk_i) then + if (we = '1') then + fifo_mem(to_integer(unsigned(w_pnt(w_pnt'left-1 downto 0)))) <= wdata_i; + end if; + end if; + end process write_large; + end generate; + end generate; - -- Read Access ---------------------------------------------------------------------------- + -- Asynchronous Read Access --------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - fifo_read_async: -- asynchronous read + fifo_read_async: if not FIFO_RSYNC generate - rdata_o <= fifo_mem(to_integer(unsigned(r_pnt(r_pnt'left-1 downto 0)))) when (fifo_depth_c > 1) else fifo_reg; + + -- just 1 FIFO entry -- + fifo_read_async_small: + if (fifo_depth_c = 1) generate + rdata_o <= fifo_reg; + end generate; + + -- more than 1 FIFO entries -- + fifo_read_async_large: + if (fifo_depth_c > 1) generate + async_r_pnt_reg: process(clk_i) + begin + if rising_edge(clk_i) then + r_pnt_ff <= r_nxt; -- individual read address register; allows mapping "async" FIFOs to memory primitives + end if; + end process async_r_pnt_reg; + rdata_o <= fifo_mem(to_integer(unsigned(r_pnt_ff(r_pnt_ff'left-1 downto 0)))); + end generate; + -- status -- free_o <= free; avail_o <= avail; half_o <= half; + end generate; - fifo_read_sync: -- synchronous read + + -- Synchronous Read Access ---------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + fifo_read_sync: if FIFO_RSYNC generate - sync_read: process(clk_i) - begin - if rising_edge(clk_i) then - if (fifo_depth_c > 1) then - rdata_o <= fifo_mem(to_integer(unsigned(r_pnt(r_pnt'left-1 downto 0)))); - else + + -- just 1 FIFO entry -- + fifo_read_sync_small: + if (fifo_depth_c = 1) generate + sync_read_small: process(clk_i) + begin + if rising_edge(clk_i) then rdata_o <= fifo_reg; end if; - end if; - end process sync_read; - -- status -- + end process sync_read_small; + end generate; + + -- more than 1 FIFO entries -- + fifo_read_sync_large: + if (fifo_depth_c > 1) generate + sync_read_large: process(clk_i) + begin + if rising_edge(clk_i) then + rdata_o <= fifo_mem(to_integer(unsigned(r_pnt(r_pnt'left-1 downto 0)))); + end if; + end process sync_read_large; + end generate; + + -- registered status -- sync_status: process(rstn_i, clk_i) begin if (rstn_i = '0') then @@ -211,6 +282,7 @@ begin half_o <= half; end if; end process sync_status; + end generate; diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index df1cef64f..62820c2fc 100644 --- a/rtl/core/neorv32_package.vhd +++ b/rtl/core/neorv32_package.vhd @@ -53,7 +53,7 @@ package neorv32_package is -- Architecture Constants ----------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090507"; -- hardware version + constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090508"; -- hardware version constant archid_c : natural := 19; -- official RISC-V architecture ID constant XLEN : natural := 32; -- native data path width diff --git a/rtl/core/neorv32_slink.vhd b/rtl/core/neorv32_slink.vhd index 2a4f8c5a5..b24b44162 100644 --- a/rtl/core/neorv32_slink.vhd +++ b/rtl/core/neorv32_slink.vhd @@ -215,10 +215,10 @@ begin rx_fifo_inst: entity neorv32.neorv32_fifo generic map ( FIFO_DEPTH => SLINK_RX_FIFO, - FIFO_WIDTH => 32+1, -- data + last-flag - FIFO_RSYNC => true, -- sync read - FIFO_SAFE => true, -- safe access - FULL_RESET => false -- no HW reset, try to infer BRAM + FIFO_WIDTH => 32+1, -- data + last-flag + FIFO_RSYNC => false, -- "async" read - update FIFO status RIGHT after write access (for slink_rx_ready_o) + FIFO_SAFE => true, -- safe access + FULL_RESET => false -- no HW reset, try to infer BRAM ) port map ( -- control -- @@ -264,10 +264,10 @@ begin tx_fifo_inst: entity neorv32.neorv32_fifo generic map ( FIFO_DEPTH => SLINK_TX_FIFO, - FIFO_WIDTH => 32+1, -- data + last-flag - FIFO_RSYNC => true, -- sync read - FIFO_SAFE => true, -- safe access - FULL_RESET => false -- no HW reset, try to infer BRAM + FIFO_WIDTH => 32+1, -- data + last-flag + FIFO_RSYNC => false, -- "async" read - update FIFO status RIGHT after read access (for slink_tx_valid_o) + FIFO_SAFE => true, -- safe access + FULL_RESET => false -- no HW reset, try to infer BRAM ) port map ( -- control --