Skip to content

Commit

Permalink
optimize FIFO component to improve mapping (#828)
Browse files Browse the repository at this point in the history
  • Loading branch information
stnolting committed Feb 23, 2024
2 parents 53930a6 + 36db5e2 commit 1900843
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 58 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) |
Expand Down
170 changes: 121 additions & 49 deletions rtl/core/neorv32_fifo.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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
Expand All @@ -211,6 +282,7 @@ begin
half_o <= half;
end if;
end process sync_status;

end generate;


Expand Down
2 changes: 1 addition & 1 deletion rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
16 changes: 8 additions & 8 deletions rtl/core/neorv32_slink.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -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 --
Expand Down Expand Up @@ -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 --
Expand Down

0 comments on commit 1900843

Please sign in to comment.