From f852caa91432aa8d4a44fb9bc721dcbf7cf956a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= <tomasz.wlostowski@cern.ch> Date: Tue, 7 Feb 2012 14:23:31 +0100 Subject: [PATCH] modules/wrsw_swcore/async_mpm: wip --- modules/wrsw_swcore/async/Manifest.py | 20 +- modules/wrsw_swcore/async/mpm_async_fifo.vhd | 99 ++++ .../wrsw_swcore/async/mpm_async_fifo_ctrl.vhd | 196 +++++++ .../wrsw_swcore/async/mpm_async_grow_fifo.vhd | 223 ++++++++ .../async/mpm_async_shrink_fifo.vhd | 158 +++++ ...ifo_mem_cell.vhd => mpm_fifo_mem_cell.vhd} | 6 +- .../wrsw_swcore/async/mpm_pipelined_mux.vhd | 87 +++ modules/wrsw_swcore/async/mpm_private_pkg.vhd | 98 ++++ modules/wrsw_swcore/async/mpm_read_path.vhd | 360 ++++++++++++ .../wrsw_swcore/async/mpm_rpath_io_block.vhd | 315 ++++++++++ modules/wrsw_swcore/async/mpm_top.vhd | 205 +++++++ modules/wrsw_swcore/async/mpm_write_path.vhd | 303 ++++++++++ modules/wrsw_swcore/async/swc_async_fifo.vhd | 106 ---- .../wrsw_swcore/async/swc_async_fifo_ctrl.vhd | 164 ------ .../wrsw_swcore/async/swc_async_grow_fifo.vhd | 138 ----- .../async/swc_async_multiport_mem.vhd | 139 ----- .../async/swc_async_shrink_fifo.vhd | 122 ---- modules/wrsw_swcore/async/swc_private_pkg.vhd | 50 -- modules/wrsw_swcore/async/swc_swcore_pkg.vhd | 540 ------------------ 19 files changed, 2060 insertions(+), 1269 deletions(-) create mode 100644 modules/wrsw_swcore/async/mpm_async_fifo.vhd create mode 100644 modules/wrsw_swcore/async/mpm_async_fifo_ctrl.vhd create mode 100644 modules/wrsw_swcore/async/mpm_async_grow_fifo.vhd create mode 100644 modules/wrsw_swcore/async/mpm_async_shrink_fifo.vhd rename modules/wrsw_swcore/async/{swc_fifo_mem_cell.vhd => mpm_fifo_mem_cell.vhd} (89%) create mode 100644 modules/wrsw_swcore/async/mpm_pipelined_mux.vhd create mode 100644 modules/wrsw_swcore/async/mpm_private_pkg.vhd create mode 100644 modules/wrsw_swcore/async/mpm_read_path.vhd create mode 100644 modules/wrsw_swcore/async/mpm_rpath_io_block.vhd create mode 100644 modules/wrsw_swcore/async/mpm_top.vhd create mode 100644 modules/wrsw_swcore/async/mpm_write_path.vhd delete mode 100644 modules/wrsw_swcore/async/swc_async_fifo.vhd delete mode 100644 modules/wrsw_swcore/async/swc_async_fifo_ctrl.vhd delete mode 100644 modules/wrsw_swcore/async/swc_async_grow_fifo.vhd delete mode 100644 modules/wrsw_swcore/async/swc_async_multiport_mem.vhd delete mode 100644 modules/wrsw_swcore/async/swc_async_shrink_fifo.vhd delete mode 100644 modules/wrsw_swcore/async/swc_private_pkg.vhd delete mode 100644 modules/wrsw_swcore/async/swc_swcore_pkg.vhd diff --git a/modules/wrsw_swcore/async/Manifest.py b/modules/wrsw_swcore/async/Manifest.py index 3caa079c..0f4e3ce0 100644 --- a/modules/wrsw_swcore/async/Manifest.py +++ b/modules/wrsw_swcore/async/Manifest.py @@ -1,7 +1,13 @@ -files = ["swc_async_grow_fifo.vhd", - "swc_async_fifo_ctrl.vhd", - "swc_fifo_mem_cell.vhd", - "swc_async_shrink_fifo.vhd", - "swc_private_pkg.vhd", - "swc_pipelined_mux.vhd", - "swc_async_multiport_mem.vhd"] +files = ["mpm_async_grow_fifo.vhd", + "mpm_async_fifo_ctrl.vhd", + "mpm_fifo_mem_cell.vhd", + "mpm_async_shrink_fifo.vhd", + "mpm_private_pkg.vhd", + "mpm_pipelined_mux.vhd", + "mpm_top.vhd", + "mpm_write_path.vhd", + "mpm_read_path.vhd", + "mpm_async_fifo.vhd", + "mpm_rpath_io_block.vhd"] + + diff --git a/modules/wrsw_swcore/async/mpm_async_fifo.vhd b/modules/wrsw_swcore/async/mpm_async_fifo.vhd new file mode 100644 index 00000000..fb2d9f33 --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_async_fifo.vhd @@ -0,0 +1,99 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.genram_pkg.all; -- for f_log2_size + +entity mpm_async_fifo is + + generic ( + g_width : integer := 11 + 1; + g_size : integer := 8); + + port ( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + + we_i : in std_logic; + d_i : in std_logic_vector(g_width-1 downto 0); + + rd_i : in std_logic; + q_o : out std_logic_vector(g_width-1 downto 0); + + full_o : out std_logic; + empty_o : out std_logic); + +end mpm_async_fifo; + +architecture rtl of mpm_async_fifo is + + component mpm_fifo_mem_cell + generic ( + g_width : integer; + g_size : integer); + port ( + clk_i : in std_logic; + wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + wd_i : in std_logic_vector(g_width-1 downto 0); + we_i : in std_logic; + ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + rd_o : out std_logic_vector(g_width-1 downto 0)); + end component; + + component mpm_async_fifo_ctrl + generic ( + g_size : integer); + port ( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + rd_i : in std_logic; + wr_i : in std_logic; + wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + full_o : out std_logic; + empty_o : out std_logic); + end component; + + signal q_comb : std_logic_vector(g_width-1 downto 0); + signal wr_addr, rd_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0); + +begin -- rtl + + + U_Mem_Mem : mpm_fifo_mem_cell + generic map ( + g_width => g_width, + g_size => g_size) + port map ( + clk_i => clk_wr_i, + wa_i => wr_addr, + wd_i => d_i, + we_i => we_i, + ra_i => rd_addr, + rd_o => q_comb); + + + U_CTRL : mpm_async_fifo_ctrl + generic map ( + g_size => g_size) + port map ( + rst_n_a_i => rst_n_a_i, + clk_wr_i => clk_wr_i, + clk_rd_i => clk_rd_i, + rd_i => rd_i, + wr_i => we_i, + wr_addr_o => wr_addr, + rd_addr_o => rd_addr, + full_o => full_o, + empty_o => empty_o); + + p_output_reg : process(clk_rd_i) + begin + if rising_edge(clk_rd_i) then + q_o <= q_comb; + end if; + end process; + +end rtl; diff --git a/modules/wrsw_swcore/async/mpm_async_fifo_ctrl.vhd b/modules/wrsw_swcore/async/mpm_async_fifo_ctrl.vhd new file mode 100644 index 00000000..645cd0d4 --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_async_fifo_ctrl.vhd @@ -0,0 +1,196 @@ +------------------------------------------------------------------------------- +-- Title : Dual clock (asynchronous) FIFO controller +-- Project : White Rabbit Switch +------------------------------------------------------------------------------- +-- File : mpm_async_fifo_ctrl.vhd +-- Author : Tomasz WÅ‚ostowski +-- Company : CERN BE-CO-HT +-- Created : 2012-01-30 +-- Last update : 2012-01-30 +-- Platform : FPGA-generic +-- Standard : VHDL'93 +-- Dependencies : genram_pkg +------------------------------------------------------------------------------- +-- Description: Gray-encoded dual clock FIFO controller and address generator. +-- Based on Xilinx Application Note "Asynchronous FIFO in Virtex-II FPGAs" by +-- P. Alfke & Generic FIFO project by Rudolf Usselmann. +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2012 CERN +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the GNU Lesser General +-- Public License as published by the Free Software Foundation; +-- either version 2.1 of the License, or (at your option) any +-- later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the GNU Lesser General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Lesser General +-- Public License along with this source; if not, download it +-- from http://www.gnu.org/licenses/lgpl-2.1.html +-- +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2012-01-30 1.0 twlostow Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.genram_pkg.all; + +entity mpm_async_fifo_ctrl is + + generic ( + g_size : integer); + + port( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + + rd_i : in std_logic; + wr_i : in std_logic; + + wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + + full_o : out std_logic; + going_full_o : out std_logic; + empty_o : out std_logic); + +end mpm_async_fifo_ctrl; + +architecture rtl of mpm_async_fifo_ctrl is + + function f_bin2gray(bin : unsigned) return unsigned is + begin + return bin(bin'left) & (bin(bin'left-1 downto 0) xor bin(bin'left downto 1)); + end f_bin2gray; + + function f_gray2bin(gray : unsigned) return unsigned is + variable bin : unsigned(gray'left downto 0); + begin + -- gray to binary + for i in 0 to gray'left loop + bin(i) := '0'; + for j in i to gray'left loop + bin(i) := bin(i) xor gray(j); + end loop; -- j + end loop; -- i + return bin; + end f_gray2bin; + + subtype t_counter is unsigned(f_log2_size(g_size) downto 0); + + type t_counter_block is record + bin, bin_next, gray, gray_next : t_counter; + bin_x, gray_x : t_counter; + end record; + + + signal rcb, wcb : t_counter_block; + signal full_int, empty_int : std_logic; + signal going_full : std_logic; + +begin -- rtl + + wcb.bin_next <= wcb.bin + 1; + wcb.gray_next <= f_bin2gray(wcb.bin_next); + + p_write_ptr : process(clk_wr_i, rst_n_a_i) + begin + if rst_n_a_i = '0' then + wcb.bin <= (others => '0'); + wcb.gray <= (others => '0'); + elsif rising_edge(clk_wr_i) then + if(wr_i = '1' and full_int = '0') then + wcb.bin <= wcb.bin_next; + wcb.gray <= wcb.gray_next; + end if; + end if; + end process; + + rcb.bin_next <= rcb.bin + 1; + rcb.gray_next <= f_bin2gray(rcb.bin_next); + + p_read_ptr : process(clk_rd_i, rst_n_a_i) + begin + if rst_n_a_i = '0' then + rcb.bin <= (others => '0'); + rcb.gray <= (others => '0'); + elsif rising_edge(clk_rd_i) then + if(rd_i = '1' and empty_int = '0') then + rcb.bin <= rcb.bin_next; + rcb.gray <= rcb.gray_next; + end if; + end if; + end process; + + p_sync_read_ptr : process(clk_wr_i) + begin + if rising_edge(clk_wr_i) then + rcb.gray_x <= rcb.gray; + end if; + end process; + + p_sync_write_ptr : process(clk_rd_i) + begin + if rising_edge(clk_rd_i) then + wcb.gray_x <= wcb.gray; + end if; + end process; + + wcb.bin_x <= f_gray2bin(wcb.gray_x); + rcb.bin_x <= f_gray2bin(rcb.gray_x); + + p_gen_empty : process(clk_rd_i, rst_n_a_i) + begin + if rst_n_a_i = '0' then + empty_int <= '1'; + elsif rising_edge (clk_rd_i) then + if(rcb.gray = wcb.gray_x or (rd_i = '1' and (wcb.gray_x = rcb.gray_next))) then + empty_int <= '1'; + else + empty_int <= '0'; + end if; + end if; + end process; + + p_gen_going_full : process(wr_i, wcb, rcb) + begin + if ((wcb.bin (wcb.bin'left-2 downto 0) = rcb.bin_x(rcb.bin_x'left-2 downto 0)) + and (wcb.bin(wcb.bin'left) /= rcb.bin_x(wcb.bin_x'left))) then + going_full <= '1'; + elsif (wr_i = '1' + and (wcb.bin_next(wcb.bin'left-2 downto 0) = rcb.bin_x(rcb.bin_x'left-2 downto 0)) + and (wcb.bin_next(wcb.bin'left) /= rcb.bin_x(rcb.bin_x'left))) then + going_full <= '1'; + else + going_full <= '0'; + end if; + end process; + + p_register_full : process(clk_wr_i, rst_n_a_i) + begin + if rst_n_a_i = '0' then + full_int <= '0'; + elsif rising_edge (clk_wr_i) then + full_int <= going_full; + end if; + end process; + + full_o <= full_int; + empty_o <= empty_int; + going_full_o <= going_full; + + wr_addr_o <= std_logic_vector(wcb.bin(wcb.bin'left-1 downto 0)); + rd_addr_o <= std_logic_vector(rcb.bin(rcb.bin'left-1 downto 0)); +end rtl; diff --git a/modules/wrsw_swcore/async/mpm_async_grow_fifo.vhd b/modules/wrsw_swcore/async/mpm_async_grow_fifo.vhd new file mode 100644 index 00000000..bae9df4d --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_async_grow_fifo.vhd @@ -0,0 +1,223 @@ + +------------------------------------------------------------------------------- +-- Title : Dual clock (asynchronous) asymmetric (1:N) FIFO +-- Project : White Rabbit Switch +------------------------------------------------------------------------------- +-- File : swc_async_grow_fifo.vhd +-- Author : Tomasz WÅ‚ostowski +-- Company : CERN BE-CO-HT +-- Created : 2012-01-30 +-- Last update : 2012-01-30 +-- Platform : FPGA-generic +-- Standard : VHDL'93 +-- Dependencies : swc_fifo_mem_cell, swc_async_fifo_ctrl, genram_pkg +------------------------------------------------------------------------------- +-- Description: Asynchronous FIFO with asymmetric (deserializing) read/write +-- ports. g_ratio words written to input port d_i are combined into a single +-- (g_ratio * g_width) word on port q_o. An additional symmetric +-- sideband channel (side_i/side_o) is provided for passing auxillary data. +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2012 CERN +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the GNU Lesser General +-- Public License as published by the Free Software Foundation; +-- either version 2.1 of the License, or (at your option) any +-- later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the GNU Lesser General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Lesser General +-- Public License along with this source; if not, download it +-- from http://www.gnu.org/licenses/lgpl-2.1.html +-- +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2012-01-30 1.0 twlostow Created +------------------------------------------------------------------------------- + + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.genram_pkg.all; -- for f_log2_size + +entity mpm_async_grow_fifo is + + generic ( + -- base data width (narrow port) + g_width : integer := 16; + -- wide/narrow data width ratio + g_ratio : integer := 6; + -- number of wide words in FIFO + g_size : integer := 8; + -- sideband channel (side_i/side_o) width + g_sideband_width : integer := 16); + + port ( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + + -- 1: write word available on (d_i) to the FIFO + we_i : in std_logic; + -- 1: perform an aligned write (i.e. at the beginning of the wide word) + align_i : in std_logic; + -- data input + d_i : in std_logic_vector(g_width-1 downto 0); + + -- 1: performs a read of a single wide word, outputted on q_o + rd_i : in std_logic; + -- registered data output + q_o : out std_logic_vector(g_width * g_ratio-1 downto 0); + + -- "Sideband" channel (for passing auxillary data, such as page indices) + side_i : in std_logic_vector(g_sideband_width-1 downto 0); + side_o : out std_logic_vector(g_sideband_width-1 downto 0); + + -- Full flag (clk_wr_i domain) + full_o : out std_logic; + -- Empty flag (clk_rd_i domain) + empty_o : out std_logic); + +end mpm_async_grow_fifo; + +architecture rtl of mpm_async_grow_fifo is + + component mpm_fifo_mem_cell + generic ( + g_width : integer; + g_size : integer); + port ( + clk_i : in std_logic; + wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + wd_i : in std_logic_vector(g_width-1 downto 0); + we_i : in std_logic; + ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + rd_o : out std_logic_vector(g_width-1 downto 0)); + end component; + + component mpm_async_fifo_ctrl + generic ( + g_size : integer); + port ( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + rd_i : in std_logic; + wr_i : in std_logic; + wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + full_o : out std_logic; + going_full_o : out std_logic; + empty_o : out std_logic); + end component; + + signal wr_sreg : std_logic_vector(g_ratio-1 downto 0); + signal wr_cell : std_logic_vector(g_ratio-1 downto 0); + signal real_we : std_logic; + signal q_int : std_logic_vector(g_width*g_ratio-1 downto 0); + signal wr_addr, rd_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0); + signal full_int : std_logic; + signal side_comb : std_logic_vector(g_sideband_width-1 downto 0); + +begin -- rtl + + -- Genrate g_ratio memory cells, which are written sequentially (each memory + -- block corresponds to a bit in wr_cell shift register) and read all at + -- once, forming a deserializer. + gen_mem_cells : for i in 0 to g_ratio-1 generate + + wr_cell(i) <= wr_sreg(i) and we_i; + + U_Mem : mpm_fifo_mem_cell + generic map ( + g_width => g_width, + g_size => g_size) + port map ( + clk_i => clk_wr_i, + wa_i => wr_addr, + wd_i => d_i, + we_i => wr_cell(i), + ra_i => rd_addr, + rd_o => q_int(g_width*(i+1) -1 downto g_width*i)); + end generate gen_mem_cells; + + -- Extra memory cell for sideband channel + U_Sideband_Mem : mpm_fifo_mem_cell + generic map ( + g_width => g_sideband_width, + g_size => g_size) + port map ( + clk_i => clk_wr_i, + wa_i => wr_addr, + wd_i => side_i, + we_i => real_we, + ra_i => rd_addr, + rd_o => side_comb); + + + U_CTRL : mpm_async_fifo_ctrl + generic map ( + g_size => g_size) + port map ( + rst_n_a_i => rst_n_a_i, + clk_wr_i => clk_wr_i, + clk_rd_i => clk_rd_i, + rd_i => rd_i, + wr_i => real_we, + wr_addr_o => wr_addr, + rd_addr_o => rd_addr, + going_full_o => full_int, +-- full_o => full_int, + empty_o => empty_o); + + + -- Per-cell write shift register control + p_write_grow_sreg : process(clk_wr_i, rst_n_a_i) + begin + if rst_n_a_i = '0' then + wr_sreg(0) <= '1'; + wr_sreg(wr_sreg'left downto 1) <= (others => '0'); + elsif rising_edge(clk_wr_i) then + if(we_i = '1') then + if(align_i = '1') then + wr_sreg(0) <= '1'; + wr_sreg(wr_sreg'left downto 1) <= (others => '0'); + else + wr_sreg <= wr_sreg(wr_sreg'left-1 downto 0) & wr_sreg(wr_sreg'left); + end if; + end if; + end if; + end process; + + real_we <= wr_cell(wr_cell'left) or (we_i and align_i); + + -- Output register on q_o. Memory cells are combinatorial, the register is + -- here to improve the timing. + p_output_reg : process(clk_rd_i, rst_n_a_i) + begin + if (rst_n_a_i = '0') then + q_o <= (others => '0'); + side_o <= (others => '0'); + elsif rising_edge(clk_rd_i) then + if(rd_i = '1') then + q_o <= q_int; + side_o <= side_comb; + end if; + end if; + end process; + + -- full flag is only active when there's no space left in the highest memory + -- cell + full_o <= full_int and wr_sreg(wr_sreg'left); + +end rtl; diff --git a/modules/wrsw_swcore/async/mpm_async_shrink_fifo.vhd b/modules/wrsw_swcore/async/mpm_async_shrink_fifo.vhd new file mode 100644 index 00000000..0af58025 --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_async_shrink_fifo.vhd @@ -0,0 +1,158 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.genram_pkg.all; -- for f_log2_size + +entity mpm_async_shrink_fifo is + + generic ( + g_width : integer; -- narrow port width + g_ratio : integer; + g_size : integer; + g_sideband_width : integer); + + port ( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + + we_i : in std_logic; + d_i : in std_logic_vector(g_width*g_ratio-1 downto 0); + + rd_i : in std_logic; + q_o : out std_logic_vector(g_width-1 downto 0); + + side_i : in std_logic_vector(g_sideband_width-1 downto 0); + side_o : out std_logic_vector(g_sideband_width-1 downto 0); + + flush_i : in std_logic := '0'; + full_o : out std_logic; + empty_o : out std_logic); + +end mpm_async_shrink_fifo; + +architecture rtl of mpm_async_shrink_fifo is + + component mpm_fifo_mem_cell + generic ( + g_width : integer; + g_size : integer); + port ( + clk_i : in std_logic; + wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + wd_i : in std_logic_vector(g_width-1 downto 0); + we_i : in std_logic; + ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + rd_o : out std_logic_vector(g_width-1 downto 0)); + end component; + + component mpm_async_fifo_ctrl + generic ( + g_size : integer); + port ( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + rd_i : in std_logic; + wr_i : in std_logic; + wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + full_o : out std_logic; + empty_o : out std_logic); + end component; + + signal rd_count : unsigned(3 downto 0); + signal real_rd : std_logic; + signal q_muxed : std_logic_vector(g_width-1 downto 0); + signal q_comb, q_reg : std_logic_vector(g_width*g_ratio-1 downto 0); + signal wr_addr, rd_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0); + signal empty_wide, empty_narrow : std_logic; + signal line_flushed : std_logic; + +begin -- rtl + + + gen_sb_mem : if(g_sideband_width > 0) generate + U_Sideband_Mem : mpm_fifo_mem_cell + generic map ( + g_width => g_sideband_width, + g_size => g_size) + port map ( + clk_i => clk_wr_i, + wa_i => wr_addr, + wd_i => side_i, + we_i => we_i, + ra_i => rd_addr, + rd_o => side_o); + end generate gen_sb_mem; + + gen_mem_cells : for i in 0 to g_ratio-1 generate + + U_Mem : mpm_fifo_mem_cell + generic map ( + g_width => g_width, + g_size => g_size) + port map ( + clk_i => clk_wr_i, + wa_i => wr_addr, + wd_i => d_i(g_width*(i+1) -1 downto g_width*i), + we_i => we_i, + ra_i => rd_addr, + rd_o => q_comb(g_width*(i+1) -1 downto g_width*i)); + end generate gen_mem_cells; + + U_CTRL : mpm_async_fifo_ctrl + generic map ( + g_size => g_size) + port map ( + rst_n_a_i => rst_n_a_i, + clk_wr_i => clk_wr_i, + clk_rd_i => clk_rd_i, + rd_i => real_rd, + wr_i => we_i, + wr_addr_o => wr_addr, + rd_addr_o => rd_addr, + full_o => full_o, + empty_o => empty_wide); + + p_read_mux : process(clk_rd_i, rst_n_a_i) + begin + if rst_n_a_i = '0' then + rd_count <= (others => '0'); + q_reg <= (others => '0'); + line_flushed <= real_rd; + empty_narrow <= '1'; + elsif rising_edge(clk_rd_i) then + + if(empty_wide = '0') then + empty_narrow <= '0'; + elsif(((rd_count = g_ratio-1 and rd_i = '1') or flush_i = '1') and empty_wide = '1') then + empty_narrow <= '1'; + end if; + + line_flushed <= real_rd; + + if(real_rd = '1')then + q_reg <= q_comb; + end if; + + if(rd_i = '1' or flush_i = '1') then + if(rd_count = g_ratio-1 or flush_i = '1') then + rd_count <= (others => '0'); + else + rd_count <= rd_count + 1; + end if; + + q_muxed <= q_reg(((to_integer(rd_count)+1)*g_width)-1 downto to_integer(rd_count)*g_width); + end if; + + end if; + end process; + + + real_rd <= '1' when (rd_count = 0) and rd_i = '1' else '0'; + q_o <= q_reg(g_width-1 downto 0) when line_flushed = '1' else q_muxed; + empty_o <= empty_narrow; + +end rtl; diff --git a/modules/wrsw_swcore/async/swc_fifo_mem_cell.vhd b/modules/wrsw_swcore/async/mpm_fifo_mem_cell.vhd similarity index 89% rename from modules/wrsw_swcore/async/swc_fifo_mem_cell.vhd rename to modules/wrsw_swcore/async/mpm_fifo_mem_cell.vhd index b4f99334..e3d5b697 100644 --- a/modules/wrsw_swcore/async/swc_fifo_mem_cell.vhd +++ b/modules/wrsw_swcore/async/mpm_fifo_mem_cell.vhd @@ -4,7 +4,7 @@ use IEEE.numeric_std.all; use work.genram_pkg.all; -entity swc_fifo_mem_cell is +entity mpm_fifo_mem_cell is generic ( g_width : integer; @@ -19,9 +19,9 @@ entity swc_fifo_mem_cell is ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); rd_o : out std_logic_vector(g_width-1 downto 0)); -end swc_fifo_mem_cell; +end mpm_fifo_mem_cell; -architecture rtl of swc_fifo_mem_cell is +architecture rtl of mpm_fifo_mem_cell is type t_mem_array is array(0 to g_size-1) of std_logic_vector(g_width-1 downto 0); signal mem : t_mem_array; diff --git a/modules/wrsw_swcore/async/mpm_pipelined_mux.vhd b/modules/wrsw_swcore/async/mpm_pipelined_mux.vhd new file mode 100644 index 00000000..de51b48e --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_pipelined_mux.vhd @@ -0,0 +1,87 @@ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.genram_pkg.all; +use work.mpm_private_pkg.all; + +entity mpm_pipelined_mux is + + generic ( + g_width : integer := 16; + g_inputs : integer := 18); + + port ( + clk_i : in std_logic; + rst_n_i : in std_logic; + + d_i : in std_logic_vector(g_inputs * g_width-1 downto 0); + q_o : out std_logic_vector(g_width-1 downto 0); + + -- select input (one hot encoded) + sel_i : in std_logic_vector(g_inputs-1 downto 0) + ); + +end mpm_pipelined_mux; + +architecture rtl of mpm_pipelined_mux is + + type t_generic_slv_array is array (integer range <>, integer range <>) of std_logic; + + constant c_first_stage_muxes : integer := (g_inputs+2)/3; + + signal first_stage : t_generic_slv_array(0 to c_first_stage_muxes-1, g_width-1 downto 0); + +begin -- rtl + + -- 1st stage, optimized for 5-input LUTs: mux each 3-input groups or 0 + -- if (sel == 11) + gen_1st_stage : for i in 0 to c_first_stage_muxes-1 generate + gen_each_bit : for j in 0 to g_width-1 generate + p_mux_or : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + first_stage(i, j) <= '0'; + else + if(sel_i(3*i + 2 downto 3*i) = "001") then + first_stage(i, j) <= d_i(i * 3 * g_width + j); + elsif (sel_i(3*i + 2 downto 3*i) = "010") then + first_stage(i, j) <= d_i(i * 3 * g_width + g_width + j); + elsif (sel_i(3*i + 2 downto 3*i) = "100") then + first_stage(i, j) <= d_i(i * 3 * g_width + 2*g_width + j); + else + first_stage(i, j) <= '0'; + end if; + end if; + end if; + end process; + end generate gen_each_bit; + end generate gen_1st_stage; + + -- 2nd stage: simply OR together the results of the 1st stage + p_2nd_stage : process(clk_i) + variable row : std_logic_vector(c_first_stage_muxes-1 downto 0); + begin + if rising_edge(clk_i) then + for j in 0 to g_width-1 loop + if rst_n_i = '0' then + q_o(j) <= '0'; + else + for i in 0 to c_first_stage_muxes-1 loop + row(i) := first_stage(i, j); + end loop; -- i + + if(unsigned(row) = 0) then + q_o(j) <= '0'; + else + q_o(j) <= '1'; + end if; + end if; + end loop; -- j in 0 to g_width-1 loop + end if; + end process; + + +end rtl; diff --git a/modules/wrsw_swcore/async/mpm_private_pkg.vhd b/modules/wrsw_swcore/async/mpm_private_pkg.vhd new file mode 100644 index 00000000..4c5c2379 --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_private_pkg.vhd @@ -0,0 +1,98 @@ +library ieee; +use ieee.std_logic_1164.all; + +package mpm_private_pkg is + + ----------------------------------------------------------------------------- + -- Components + ----------------------------------------------------------------------------- + + component mpm_pipelined_mux + generic ( + g_width : integer; + g_inputs : integer); + port ( + clk_i : in std_logic; + rst_n_i : in std_logic; + d_i : in std_logic_vector(g_inputs * g_width-1 downto 0); + q_o : out std_logic_vector(g_width-1 downto 0); + sel_i : in std_logic_vector(g_inputs-1 downto 0)); + end component; + + component mpm_async_grow_fifo + generic ( + g_width : integer; + g_ratio : integer; + g_size : integer; + g_sideband_width : integer); + port ( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + we_i : in std_logic; + align_i : in std_logic; + d_i : in std_logic_vector(g_width-1 downto 0); + rd_i : in std_logic; + q_o : out std_logic_vector(g_width * g_ratio-1 downto 0); + side_i : in std_logic_vector(g_sideband_width-1 downto 0); + side_o : out std_logic_vector(g_sideband_width-1 downto 0); + full_o : out std_logic; + empty_o : out std_logic); + end component; + + component mpm_async_shrink_fifo + generic ( + g_width : integer; + g_ratio : integer; + g_size : integer; + g_sideband_width : integer); + port ( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + we_i : in std_logic; + d_i : in std_logic_vector(g_width*g_ratio-1 downto 0); + rd_i : in std_logic; + q_o : out std_logic_vector(g_width-1 downto 0); + side_i : in std_logic_vector(g_sideband_width-1 downto 0); + side_o : out std_logic_vector(g_sideband_width-1 downto 0); + flush_i : in std_logic := '0'; + full_o : out std_logic; + empty_o : out std_logic); + end component; + + component mpm_async_fifo + generic ( + g_width : integer; + g_size : integer); + port ( + rst_n_a_i : in std_logic; + clk_wr_i : in std_logic; + clk_rd_i : in std_logic; + we_i : in std_logic; + d_i : in std_logic_vector(g_width-1 downto 0); + rd_i : in std_logic; + q_o : out std_logic_vector(g_width-1 downto 0); + full_o : out std_logic; + empty_o : out std_logic); + end component; + + function f_slice ( + x : std_logic_vector; + index : integer; + len : integer) return std_logic_vector; + +end mpm_private_pkg; + +package body mpm_private_pkg is + + function f_slice ( + x : std_logic_vector; + index : integer; + len : integer) return std_logic_vector is + begin + return x((index + 1) * len - 1 downto index * len); + end f_slice; + + +end mpm_private_pkg; diff --git a/modules/wrsw_swcore/async/mpm_read_path.vhd b/modules/wrsw_swcore/async/mpm_read_path.vhd new file mode 100644 index 00000000..1f12d343 --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_read_path.vhd @@ -0,0 +1,360 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.mpm_private_pkg.all; + +use work.gencores_pkg.all; -- for f_rr_arbitrate +use work.genram_pkg.all; -- for f_log2_size + +entity mpm_read_path is + + generic ( + g_data_width : integer; + g_ratio : integer; + g_page_size : integer; + g_num_pages : integer; + g_num_ports : integer; + g_fifo_size : integer; + g_page_addr_width : integer; + g_partial_select_width : integer; + g_max_packet_size : integer + ); + + port( + -- I/O ports clock (slow) + clk_io_i : in std_logic; + -- Memory/Core clock (fast) + clk_core_i : in std_logic; + rst_n_io_i : in std_logic; + rst_n_core_i : in std_logic; + +-- read-write ports I/F (streaming) + rport_d_o : out std_logic_vector (g_num_ports * g_data_width -1 downto 0); + rport_dvalid_o : out std_logic_vector (g_num_ports-1 downto 0); + rport_dlast_o : out std_logic_vector (g_num_ports-1 downto 0); + rport_dsel_o : out std_logic_vector(g_partial_select_width -1 downto 0); + rport_dreq_i : in std_logic_vector (g_num_ports-1 downto 0); + rport_abort_i : in std_logic_vector (g_num_ports-1 downto 0); + rport_pg_addr_i : in std_logic_vector (g_num_ports * g_page_addr_width -1 downto 0); + rport_pg_req_o : out std_logic_vector(g_num_ports-1 downto 0); + rport_pg_valid_i : in std_logic_vector (g_num_ports-1 downto 0); + + -- Linked List I/F (I/O clock domain) + ll_addr_o : out std_logic_vector(g_page_addr_width-1 downto 0); + ll_data_i : in std_logic_vector(g_page_addr_width+1 downto 0); + + -- F. B. Memory I/F + fbm_addr_o : out std_logic_vector(f_log2_size(g_num_pages * g_page_size / g_ratio)-1 downto 0); + fbm_data_i : in std_logic_vector(g_ratio * g_data_width -1 downto 0) + ); + +end mpm_read_path; + +architecture rtl of mpm_read_path is + + component mpm_rpath_io_block + generic ( + g_data_width : integer; + g_page_addr_width : integer; + g_page_size : integer; + g_partial_select_width : integer; + g_ratio : integer; + g_max_packet_size : integer); + port ( + clk_io_i : in std_logic; + rst_n_io_i : in std_logic; + rport_d_o : out std_logic_vector(g_page_addr_width-1 downto 0); + rport_dvalid_o : out std_logic; + rport_dlast_o : out std_logic; + rport_dsel_o : out std_logic_vector(g_partial_select_width-1 downto 0); + rport_dreq_i : in std_logic; + rport_abort_i : in std_logic; + rport_pg_req_o : out std_logic; + rport_pg_valid_i : in std_logic; + rport_pg_addr_i : in std_logic_vector(g_page_addr_width-1 downto 0); + ll_req_o : out std_logic; + ll_grant_i : in std_logic; + ll_addr_o : out std_logic_vector(g_page_addr_width-1 downto 0); + ll_data_i : in std_logic_vector(g_page_addr_width + 1 downto 0); + pf_full_i : in std_logic; + pf_we_o : out std_logic; + pf_pg_addr_o : out std_logic_vector(g_page_addr_width-1 downto 0); + pf_pg_lines_o : out std_logic_vector(f_log2_size(g_page_size / g_ratio)-1 downto 0); + df_empty_i : in std_logic; + df_flush_o : out std_logic; + df_rd_o : out std_logic; + df_d_i : in std_logic_vector(g_data_width-1 downto 0)); + end component; + + + constant c_page_count_width : integer := f_log2_size(g_max_packet_size / g_page_size + 1); + constant c_line_size_width : integer := f_log2_size(g_page_size / g_ratio); + constant c_fbm_data_width : integer := g_ratio * g_data_width; + constant c_fbm_entries : integer := g_num_pages * g_page_size / g_ratio; + constant c_fbm_addr_width : integer := f_log2_size(c_fbm_entries); + constant c_fifo_sideband_width : integer := c_fbm_addr_width; + + type t_mpm_read_port is record + d : std_logic_vector(g_data_width-1 downto 0); + d_valid : std_logic; + d_last : std_logic; + d_sel : std_logic_vector(g_partial_select_width-1 downto 0); + d_req : std_logic; + pg_addr : std_logic_vector(g_page_addr_width-1 downto 0); + pg_valid : std_logic; + pg_req : std_logic; + abort : std_logic; + + end record; + + type t_mpm_read_port_array is array (integer range <>) of t_mpm_read_port; + + type t_rport_io_state is record + -- Data FIFO output port + df_rd : std_logic; + df_empty : std_logic; + df_flush : std_logic; + df_q : std_logic_vector(c_fbm_data_width -1 downto 0); + + -- Page FIFO input port + pf_full : std_logic; + pf_we : std_logic; + pf_pg_addr : std_logic_vector(g_page_addr_width-1 downto 0); + pf_pg_lines : std_logic_vector(c_line_size_width-1 downto 0); + pf_d : std_logic_vector(c_line_size_width + g_page_addr_width -1 downto 0); + + -- Linked list address & arbitration + ll_req : std_logic; + ll_grant_d : std_logic_vector(2 downto 0); + ll_addr : std_logic_vector(g_page_addr_width-1 downto 0); + end record; + + -- clk_core_i domain state + type t_rport_core_state is record + df_full : std_logic; + df_we : std_logic; + + + + pf_q : std_logic_vector(g_page_addr_width + c_line_size_width-1 downto 0); + pf_rd : std_logic; + pf_empty : std_logic; + pg_remaining : std_logic_vector(c_line_size_width - 1 downto 0); + fbm_addr : std_logic_vector(c_fbm_addr_width - 1 downto 0); + mem_req : std_logic; + mem_grant_d : std_logic_vector(3 downto 0); + end record; + +------------------------------------------------------------------------------- +-- Functions +------------------------------------------------------------------------------- + + type t_rport_core_state_array is array(integer range <>) of t_rport_core_state; + type t_rport_io_state_array is array(integer range <>) of t_rport_io_state; + + signal mem_req, mem_grant : std_logic_vector(g_num_ports-1 downto 0); + signal ll_req, ll_grant : std_logic_vector(g_num_ports-1 downto 0); + + signal io : t_rport_io_state_array(g_num_ports-1 downto 0); + signal core : t_rport_core_state_array(g_num_ports-1 downto 0); + + signal rport : t_mpm_read_port_array(g_num_ports-1 downto 0); + + signal rd_mux_a_in : std_logic_vector(g_num_ports * c_fbm_data_width -1 downto 0); + signal rd_mux_sel : std_logic_vector(g_num_ports-1 downto 0); + + signal fbm_data_reg : std_logic_vector(c_fbm_data_width-1 downto 0); + +begin -- rtl + +-- I/O structure serialization/deserialization + gen_serialize_ios : for i in 0 to g_num_ports-1 generate + + rport_d_o (g_data_width * (i+1) - 1 downto g_data_width * i) <= + rport(i).d; + rport_dvalid_o(i) <= + rport(i).d_valid; + rport_dlast_o(i) <= + rport(i).d_last; + rport_dsel_o(g_partial_select_width * (i+1) - 1 downto g_partial_select_width * i) <= + rport(i).d_sel; + + rport(i).d_req <= rport_dreq_i(i); + rport(i).abort <= rport_abort_i(i); + rport(i).pg_addr <= f_slice(rport_pg_addr_i, i, g_page_addr_width); + rport(i).pg_valid <= rport_pg_valid_i(i); + rport_pg_req_o(i) <= rport(i).pg_req; + + end generate gen_serialize_ios; + + + + -- The actual round-robin arbiter for muxing memory accesses. + p_mem_arbiter : process(clk_core_i) + begin + if rising_edge(clk_core_i) then + if rst_n_core_i = '0' then + mem_grant <= (others => '0'); + else + f_rr_arbitrate(mem_req, mem_grant, mem_grant); + end if; + end if; + end process; + + gen_mem_access_arbiter : for i in 0 to g_num_ports-1 generate + + mem_req(i) <= core(i).mem_req and not core(i).mem_grant_d(0); + core(i).mem_grant_d(0) <= mem_grant(i); + + -- Delay the grant signal to generate enables for each pipeline stage + process(clk_core_i) + begin + if rising_edge(clk_core_i) then + if rst_n_core_i = '0' then + core(i).mem_grant_d(3 downto 1) <= (others => '0'); + else + core(i).mem_grant_d(3) <= core(i).mem_grant_d(2); + core(i).mem_grant_d(2) <= core(i).mem_grant_d(1); + core(i).mem_grant_d(1) <= core(i).mem_grant_d(0); + end if; + end if; + end process; + end generate gen_mem_access_arbiter; + + gen_mux_inputs : for i in 0 to g_num_ports-1 generate + rd_mux_a_in(c_fbm_addr_width * (i + 1) - 1 downto c_fbm_addr_width * i) <= core(i).fbm_addr; + rd_mux_sel(i) <= core(i).mem_grant_d(0); + end generate gen_mux_inputs; + + U_Rd_Address_Mux : mpm_pipelined_mux + generic map ( + g_width => c_fbm_addr_width, + g_inputs => g_num_ports) + port map ( + clk_i => clk_core_i, + rst_n_i => rst_n_core_i, + d_i => rd_mux_a_in, + q_o => fbm_addr_o, + sel_i => rd_mux_sel); + + p_fbm_data_reg : process(clk_core_i) + begin + if rising_edge(clk_core_i) then + fbm_data_reg <= fbm_data_i; + end if; + end process; + + + gen_fifos : for i in 0 to g_num_ports-1 generate + U_Page_Fifo : mpm_async_fifo + generic map ( + g_width => g_page_addr_width + 1, + g_size => 8) + port map ( + rst_n_a_i => rst_n_core_i, + clk_wr_i => clk_io_i, + clk_rd_i => clk_core_i, + we_i => io(i).pf_we, + d_i => io(i).pf_d, + rd_i => core(i).pf_rd, + q_o => core(i).pf_q, + full_o => io(i).pf_full, + empty_o => core(i).pf_empty); + + U_Output_Fifo : mpm_async_shrink_fifo + generic map ( + g_width => g_data_width, + g_ratio => g_ratio, + g_size => g_fifo_size, + g_sideband_width => 0) + port map ( + rst_n_a_i => rst_n_core_i, + clk_wr_i => clk_core_i, + clk_rd_i => clk_io_i, + we_i => core(i).df_we, + d_i => fbm_data_reg, + rd_i => io(i).df_rd, + q_o => io(i).df_q, + side_i => "", + flush_i => io(i).df_flush, + full_o => core(i).df_full, + empty_o => io(i).df_empty); + + end generate gen_fifos; + + +-- The arbiter for accessing the linked list + p_ll_arbiter : process(clk_io_i) + begin + if rising_edge(clk_io_i) then + if rst_n_io_i = '0' then + ll_grant <= (others => '0'); + else + f_rr_arbitrate(ll_req, ll_grant, ll_grant); + end if; + end if; + end process; + + gen_ll_access_arbiter : for i in 0 to g_num_ports-1 generate + ll_req(i) <= io(i).ll_req and not io(i).ll_grant_d(0); + io(i).ll_grant_d(0) <= ll_grant(i); + end generate gen_ll_access_arbiter; + + p_ll_mux_addr : process(clk_io_i) + variable muxed : std_logic_vector(g_page_addr_width-1 downto 0); + begin + if rising_edge(clk_io_i) then + if rst_n_io_i = '0' then + ll_addr_o <= (others => '0'); + else + for i in 0 to g_num_ports-1 loop + if(io(i).ll_grant_d(0) = '1') then + muxed := io(i).ll_addr; + end if; + end loop; -- i + ll_addr_o <= muxed; + end if; + end if; + end process; + + + gen_output_controllers : for i in 0 to g_num_ports-1 generate + U_Output_Ctrl : mpm_rpath_io_block + generic map ( + g_data_width => g_data_width, + g_page_addr_width => g_page_addr_width, + g_page_size => g_page_size, + g_partial_select_width => g_partial_select_width, + g_ratio => g_ratio, + g_max_packet_size => g_max_packet_size) + port map ( + clk_io_i => clk_io_i, + rst_n_io_i => rst_n_io_i, + rport_d_o => rport(i).d, + rport_dvalid_o => rport(i).d_valid, + rport_dlast_o => rport(i).d_last, + rport_dsel_o => rport(i).d_sel, + rport_dreq_i => rport(i).d_req, + rport_abort_i => rport(i).abort, + rport_pg_req_o => rport(i).pg_req, + rport_pg_valid_i => rport(i).pg_valid, + rport_pg_addr_i => rport(i).pg_addr, + ll_req_o => io(i).ll_req, + ll_grant_i => io(i).ll_grant_d(2), + ll_addr_o => io(i).ll_addr, + ll_data_i => ll_data_i, + pf_full_i => io(i).pf_full, + pf_we_o => io(i).pf_we, + pf_pg_addr_o => io(i).pf_pg_addr, + pf_pg_lines_o => io(i).pf_pg_lines, + df_empty_i => io(i).df_empty, + df_flush_o => io(i).df_flush, + df_rd_o => io(i).df_rd, + df_d_i => io(i).df_q); + + io(i).pf_d <= io(i).pf_pg_lines & io(i).pf_pg_addr; + end generate gen_output_controllers; + + +end rtl; diff --git a/modules/wrsw_swcore/async/mpm_rpath_io_block.vhd b/modules/wrsw_swcore/async/mpm_rpath_io_block.vhd new file mode 100644 index 00000000..37e723a9 --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_rpath_io_block.vhd @@ -0,0 +1,315 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.gencores_pkg.all; +use work.genram_pkg.all; + +entity mpm_rpath_io_block is + + generic ( + g_data_width : integer; + g_page_addr_width : integer; + g_page_size : integer; + g_partial_select_width : integer; + g_ratio : integer; + g_max_packet_size : integer); + + port ( + clk_io_i : in std_logic; + rst_n_io_i : in std_logic; + +-- Read Port Interface + rport_d_o : out std_logic_vector(g_page_addr_width-1 downto 0); + rport_dvalid_o : out std_logic; + rport_dlast_o : out std_logic; + rport_dsel_o : out std_logic_vector(g_partial_select_width-1 downto 0); + rport_dreq_i : in std_logic; + rport_abort_i : in std_logic; + rport_pg_req_o : out std_logic; + rport_pg_valid_i : in std_logic; + rport_pg_addr_i : in std_logic_vector(g_page_addr_width-1 downto 0); + +-- Linked List Interface + ll_req_o : out std_logic; + ll_grant_i : in std_logic; + ll_addr_o : out std_logic_vector(g_page_addr_width-1 downto 0); + ll_data_i : in std_logic_vector(g_page_addr_width + 1 downto 0); + +-- Page FIFO interface + pf_full_i : in std_logic; + pf_we_o : out std_logic; + pf_pg_addr_o : out std_logic_vector(g_page_addr_width-1 downto 0); + pf_pg_lines_o : out std_logic_vector(f_log2_size(g_page_size / g_ratio)-1 downto 0); + +-- Data FIFO interface + df_empty_i : in std_logic; + df_flush_o : out std_logic; + df_rd_o : out std_logic; + df_d_i : in std_logic_vector(g_data_width-1 downto 0) + ); + +end mpm_rpath_io_block; + +architecture behavioral of mpm_rpath_io_block is + + constant c_lines_per_page : integer := g_page_size/g_ratio; + constant c_page_lines_width : integer := f_log2_size(c_lines_per_page + 1); + constant c_page_size_width : integer := f_log2_size(g_page_size + 1); + constant c_word_count_width : integer := f_log2_size(g_max_packet_size + 1); + + function f_fast_div_pagesize + (x : unsigned; + y : integer) return unsigned is + + type t_div_factor is record + inc : boolean; + mul : integer; + shift : integer; + end record; + + type t_div_factor_array is array (1 to 10) of t_div_factor; + + constant c_div_factors : t_div_factor_array := + ((false, 1, 0), + (false, 1, 1), + (true, 85, 8), + (false, 1, 2), + (true, 51, 8), + (true, 85, 9), + (true, 73, 9), + (false, 1, 3), + (true, 227, 11), + (true, 51, 9)); + + variable tmp : unsigned(x'left + 11 downto 0); + variable result : unsigned(c_page_lines_width-1 downto 0); + + begin + + if(c_div_factors(y).inc) then + tmp := (x+1) * to_unsigned(c_div_factors(y).mul, 11); + else + tmp := x * to_unsigned(c_div_factors(y).mul, 11); + end if; + + return tmp(c_page_lines_width - 1 + c_div_factors(y).shift downto c_div_factors(y).shift); + end f_fast_div_pagesize; + + + type t_ll_entry is record + valid : std_logic; + eof : std_logic; + next_page : std_logic_vector(g_page_addr_width-1 downto 0); + dsel : std_logic_vector(g_partial_select_width-1 downto 0); + size : std_logic_vector(f_log2_size(g_page_size)-1 downto 0); + end record; + + + + -- Page fetcher signals + type t_page_fetch_state is (FIRST_PAGE, NEXT_LINK, WAIT_LAST_ACK, WAIT_ACK); + signal page_state : t_page_fetch_state; + signal cur_page : std_logic_vector(g_page_addr_width-1 downto 0); + signal cur_ll : t_ll_entry; + + -- Page fetch <> FIFO / output FSM signals + + -- Address of the current page + signal fetch_pg_addr : std_logic_vector(g_page_addr_width-1 downto 0); + -- Number of words in the page (1 = 1 word...g_page_size-1 == full page) + signal fetch_pg_words : unsigned(c_page_lines_width-1 downto 0); + -- Number of FBM lines used by this page (1 = 1 line, etc.) + signal fetch_pg_lines : unsigned(c_page_lines_width-1 downto 0); + -- Partial select bits for the last word of the packet + signal fetch_dsel : std_logic_vector(g_partial_select_width-1 downto 0); + -- Is the page the last one in the current chain? + signal fetch_last : std_logic; + -- Is the page the first one in the current chain? + signal fetch_first : std_logic; + -- Acknowledge of the transfer on pg_addr/ast/valid/remaining/dsel lines. The + -- fetcher will proceed with the next page/packet only after getting an ACK. + signal fetch_ack : std_logic; + -- When HI, pg_addr/last/remaining/dsel contain a valid page entry. + signal fetch_valid : std_logic; + -- When HI, fetcher aborts fetching the current page chain and proceeds to the + -- next packet. + signal fetch_abort : std_logic; + + signal saved_dsel : std_logic_vector(g_partial_select_width-1 downto 0); + +-- Datapath signals + signal df_we_d0 : std_logic; + signal last_page : std_logic; + signal words_total : unsigned(c_word_count_width-1 downto 0); + signal words_xmitted : unsigned(c_word_count_width-1 downto 0); + + signal d_last_int, d_valid_int, df_rd_int : std_logic; + signal pf_we_int : std_logic; + +begin -- behavioral + + + fetch_abort <= '0'; -- FIXME: add support for ABORT + + p_gen_page_ack : process(clk_io_i) + begin + if rising_edge(clk_io_i) then + if rst_n_io_i = '0' then + fetch_ack <= '0'; + else + fetch_ack <= pf_we_int; + end if; + end if; + end process; + + pf_we_int <= fetch_valid and not pf_full_i; + pf_we_o <= pf_we_int; + pf_pg_addr_o <= fetch_pg_addr; + pf_pg_lines_o <= std_logic_vector(fetch_pg_lines); + + p_count_words : process(clk_io_i) + begin + if rising_edge(clk_io_i) then + if rst_n_io_i = '0' or (d_last_int = '1' and d_valid_int = '1') then + words_total <= (others => '0'); + words_xmitted <= to_unsigned(1, words_xmitted'length); + else + + if(fetch_last = '1' and fetch_ack = '1') then + saved_dsel <= fetch_dsel; + end if; + + if(df_rd_int = '1') then + words_xmitted <= words_xmitted + 1; + end if; + + if(fetch_ack = '1') then + if(fetch_first = '1') then + words_total <= fetch_pg_words; + else + words_total <= words_total + fetch_pg_words; + end if; + end if; + end if; + end if; + end process; + + d_last_int <= '1' when (words_total = words_xmitted) else '0'; + + + df_rd_int <= rport_dreq_i and not df_empty_i; + df_rd_o <= df_rd_int; + + p_gen_d_valid : process(clk_io_i) + begin + if rising_edge(clk_io_i) then + if rst_n_io_i = '0' then + d_valid_int <= '0'; + else + d_valid_int <= df_rd_int; + end if; + end if; + end process; + + df_flush_o <= df_rd_int and d_last_int; + + rport_dvalid_o <= d_valid_int; + rport_dlast_o <= d_last_int; + rport_d_o <= df_d_i; + rport_dsel_o <= saved_dsel when (words_total = words_xmitted) else (others => '1'); + + +------------------------------------------------------------------------------- +-- Page fetcher logic +------------------------------------------------------------------------------- + + -- pointer to the next page (shared with page size and partial select) + cur_ll.next_page <= ll_data_i(g_page_addr_width-1 downto 0); + -- 1: last page in the chain + cur_ll.eof <= ll_data_i(g_page_addr_width); + -- 1: page is valid + cur_ll.valid <= ll_data_i(g_page_addr_width+1); + -- 1: number of the words in page (1 = 1 word .. g_page_size-1 = full page) + cur_ll.size <= ll_data_i(c_page_size_width-1 downto 0); + -- 1: partial select bits (number of bytes in the last word of the page. For + -- 16-bit datapath: 0 = 1 byte, 1 = 2 bytes, etc.) + cur_ll.dsel <= ll_data_i(g_page_addr_width-1 downto g_page_addr_width-g_partial_select_width); + + p_page_fsm : process(clk_io_i) + begin + if rising_edge(clk_io_i) then + if rst_n_io_i = '0' then + page_state <= FIRST_PAGE; + + fetch_valid <= '0'; + rport_pg_req_o <= '0'; + ll_req_o <= '0'; + + else + case page_state is +-- request the 1st page of the packet from the Read port interface. Once got +-- the 1st address, go to FIRST_LL state + when FIRST_PAGE => + + if(rport_pg_valid_i = '1') then + rport_pg_req_o <= '0'; + cur_page <= rport_pg_addr_i; + ll_req_o <= '1'; + ll_addr_o <= rport_pg_addr_i; + page_state <= NEXT_LINK; + fetch_first <= '1'; + else + rport_pg_req_o <= '1'; + end if; + +-- fetch the length (or the link to the next packet) from the LL for the +-- current page + when NEXT_LINK => + if(fetch_abort = '1') then + page_state <= FIRST_PAGE; + ll_req_o <= '0'; + elsif(ll_grant_i = '1' and cur_ll.valid = '1') then + cur_page <= cur_ll.next_page; + + if(cur_ll.eof = '1') then + page_state <= WAIT_LAST_ACK; + fetch_pg_words <= unsigned(cur_ll.size); + fetch_pg_lines <= f_fast_div_pagesize(unsigned(cur_ll.size), g_ratio); + fetch_dsel <= cur_ll.dsel; + fetch_valid <= '1'; + fetch_last <= '1'; + else + page_state <= WAIT_ACK; + fetch_pg_addr <= cur_page; + fetch_valid <= '1'; + fetch_last <= '0'; + end if; + ll_req_o <= '0'; + else + ll_req_o <= '1'; + end if; + + when WAIT_ACK => + if(fetch_abort = '1') then + page_state <= FIRST_PAGE; + elsif(fetch_ack = '1') then + ll_req_o <= '1'; + fetch_first <= '0'; + page_state <= NEXT_LINK; + end if; + + when WAIT_LAST_ACK => + if(fetch_ack = '1') then + rport_pg_req_o <= '1'; + fetch_first <= '0'; + page_state <= FIRST_PAGE; + end if; + + end case; + end if; + end if; + end process; + + +end behavioral; diff --git a/modules/wrsw_swcore/async/mpm_top.vhd b/modules/wrsw_swcore/async/mpm_top.vhd new file mode 100644 index 00000000..c68ec3ee --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_top.vhd @@ -0,0 +1,205 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.gencores_pkg.all; -- for f_rr_arbitrate +use work.genram_pkg.all; -- for f_log2_size + +use work.mpm_private_pkg.all; + +entity mpm_top is + generic ( + g_data_width : integer := 18; + g_ratio : integer := 8; + g_page_size : integer := 64; + g_num_pages : integer := 2048; + g_num_ports : integer := 18; + g_fifo_size : integer := 8; + g_page_addr_width : integer := 11; + g_partial_select_width : integer := 1; + g_max_packet_size : integer := 10000 + ); + + port( + -- I/O ports clock (slow) + clk_io_i : in std_logic; + -- Memory/Core clock (fast) + clk_core_i : in std_logic; + rst_n_i : in std_logic; + +-- read-write ports I/F (streaming) + wport_d_i : in std_logic_vector (g_num_ports * g_data_width -1 downto 0); + wport_dvalid_i : in std_logic_vector (g_num_ports-1 downto 0); + wport_dlast_i : in std_logic_vector (g_num_ports-1 downto 0); + wport_pg_addr_i : in std_logic_vector (g_num_ports * g_page_addr_width -1 downto 0); + wport_pg_req_o : out std_logic_vector(g_num_ports -1 downto 0); + wport_dreq_o : out std_logic_vector (g_num_ports-1 downto 0); + + + rport_d_o : out std_logic_vector (g_num_ports * g_data_width -1 downto 0); + rport_dvalid_o : out std_logic_vector (g_num_ports-1 downto 0); + rport_dlast_o : out std_logic_vector (g_num_ports-1 downto 0); + rport_dsel_o : out std_logic_vector(g_partial_select_width -1 downto 0); + rport_dreq_i : in std_logic_vector (g_num_ports-1 downto 0); + rport_abort_i : in std_logic_vector (g_num_ports-1 downto 0); + rport_pg_addr_i : in std_logic_vector (g_num_ports * g_page_addr_width -1 downto 0); + rport_pg_valid_i : in std_logic_vector (g_num_ports-1 downto 0); + rport_pg_req_o : out std_logic_vector (g_num_ports-1 downto 0); + + ll_addr_o : out std_logic_vector(g_page_addr_width-1 downto 0); + ll_data_i : in std_logic_vector(g_page_addr_width+1 downto 0) + ); + +end mpm_top; + +architecture rtl of mpm_top is + + signal rst_n_core : std_logic; + signal rst_n_io : std_logic; + + component mpm_write_path + generic ( + g_data_width : integer; + g_ratio : integer; + g_page_size : integer; + g_num_pages : integer; + g_num_ports : integer; + g_fifo_size : integer; + g_page_addr_width : integer; + g_partial_select_width : integer); + port ( + clk_io_i : in std_logic; + clk_core_i : in std_logic; + rst_n_io_i : in std_logic; + rst_n_core_i : in std_logic; + wport_d_i : in std_logic_vector (g_num_ports * g_data_width -1 downto 0); + wport_dvalid_i : in std_logic_vector (g_num_ports-1 downto 0); + wport_dlast_i : in std_logic_vector (g_num_ports-1 downto 0); + wport_pg_addr_i : in std_logic_vector (g_num_ports * g_page_addr_width -1 downto 0); + wport_pg_req_o : out std_logic_vector(g_num_ports -1 downto 0); + wport_dreq_o : out std_logic_vector (g_num_ports-1 downto 0); + fbm_addr_o : out std_logic_vector(f_log2_size(g_num_pages * g_page_size / g_ratio)-1 downto 0); + fbm_data_o : out std_logic_vector(g_ratio * g_data_width -1 downto 0); + fbm_we_o : out std_logic); + end component; + + component mpm_read_path + generic ( + g_data_width : integer; + g_ratio : integer; + g_page_size : integer; + g_num_pages : integer; + g_num_ports : integer; + g_fifo_size : integer; + g_page_addr_width : integer; + g_partial_select_width : integer; + g_max_packet_size : integer); + port ( + clk_io_i : in std_logic; + clk_core_i : in std_logic; + rst_n_i : in std_logic; + rport_d_o : out std_logic_vector (g_num_ports * g_data_width -1 downto 0); + rport_dvalid_o : out std_logic_vector (g_num_ports-1 downto 0); + rport_dlast_o : out std_logic_vector (g_num_ports-1 downto 0); + rport_dsel_o : out std_logic_vector(g_partial_select_width -1 downto 0); + rport_dreq_i : in std_logic_vector (g_num_ports-1 downto 0); + rport_abort_i : in std_logic_vector (g_num_ports-1 downto 0); + rport_pg_addr_i : in std_logic_vector (g_num_ports * g_page_addr_width -1 downto 0); + rport_pg_req_o : out std_logic_vector(g_num_ports-1 downto 0); + rport_pg_valid_i : in std_logic_vector (g_num_ports-1 downto 0); + ll_addr_o : out std_logic_vector(g_page_addr_width-1 downto 0); + ll_data_i : in std_logic_vector(g_page_addr_width+1 downto 0); + fbm_addr_o : out std_logic_vector(f_log2_size(g_num_pages * g_page_size / g_ratio)-1 downto 0); + fbm_data_i : in std_logic_vector(g_ratio * g_data_width -1 downto 0)); + end component; + + signal fbm_wr_addr, fbm_rd_addr : std_logic_vector(f_log2_size(g_num_pages * g_page_size / g_ratio)-1 downto 0); + signal fbm_wr_data, fbm_rd_data : std_logic_vector(g_ratio * g_data_width -1 downto 0); + signal fbm_we : std_logic; + +begin -- rtl + + + + -- Reset synchronizer for the core clock domain + U_Sync_Reset_Coreclk : gc_sync_ffs + port map ( + clk_i => clk_core_i, + rst_n_i => '1', + data_i => rst_n_i, + synced_o => rst_n_core); + + rst_n_io <= rst_n_i; + + U_Write_Path : mpm_write_path + generic map ( + g_data_width => g_data_width, + g_ratio => g_ratio, + g_page_size => g_page_size, + g_num_pages => g_num_pages, + g_num_ports => g_num_ports, + g_fifo_size => g_fifo_size, + g_page_addr_width => g_page_addr_width, + g_partial_select_width => g_partial_select_width) + port map ( + clk_io_i => clk_io_i, + clk_core_i => clk_core_i, + rst_n_io_i => rst_n_io, + rst_n_core_i => rst_n_core, + wport_d_i => wport_d_i, + wport_dvalid_i => wport_dvalid_i, + wport_dlast_i => wport_dlast_i, + wport_pg_addr_i => wport_pg_addr_i, + wport_pg_req_o => wport_pg_req_o, + wport_dreq_o => wport_dreq_o, + fbm_addr_o => fbm_wr_addr, + fbm_data_o => fbm_wr_data, + fbm_we_o => fbm_we); + + U_Read_Path : mpm_read_path + generic map ( + g_data_width => g_data_width, + g_ratio => g_ratio, + g_page_size => g_page_size, + g_num_pages => g_num_pages, + g_num_ports => g_num_ports, + g_fifo_size => g_fifo_size, + g_page_addr_width => g_page_addr_width, + g_partial_select_width => g_partial_select_width, + g_max_packet_size => g_max_packet_size) + port map ( + clk_io_i => clk_io_i, + clk_core_i => clk_core_i, + rst_n_i => rst_n_i, + rport_d_o => rport_d_o, + rport_dvalid_o => rport_dvalid_o, + rport_dlast_o => rport_dlast_o, + rport_dsel_o => rport_dsel_o, + rport_dreq_i => rport_dreq_i, + rport_abort_i => rport_abort_i, + rport_pg_addr_i => rport_pg_addr_i, + rport_pg_req_o => rport_pg_req_o, + rport_pg_valid_i => rport_pg_valid_i, + ll_addr_o => ll_addr_o, + ll_data_i => ll_data_i, + fbm_addr_o => fbm_rd_addr, + fbm_data_i => fbm_rd_data); + + + -- The memory itself. + U_F_B_Memory : generic_dpram + generic map ( + g_data_width => g_data_width * g_ratio, + g_size => g_num_pages * (g_page_size / g_ratio)) + port map ( + rst_n_i => rst_n_core, + clka_i => clk_core_i, + wea_i => fbm_we, + aa_i => fbm_wr_addr, + da_i => fbm_wr_data, + clkb_i => clk_core_i, + web_i => '0', + ab_i => fbm_rd_addr, + qb_o => fbm_rd_data); + +end rtl; diff --git a/modules/wrsw_swcore/async/mpm_write_path.vhd b/modules/wrsw_swcore/async/mpm_write_path.vhd new file mode 100644 index 00000000..78ef5b6d --- /dev/null +++ b/modules/wrsw_swcore/async/mpm_write_path.vhd @@ -0,0 +1,303 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.mpm_private_pkg.all; + +use work.gencores_pkg.all; -- for f_rr_arbitrate +use work.genram_pkg.all; -- for f_log2_size + +entity mpm_write_path is + + generic ( + g_data_width : integer := 10; + g_ratio : integer := 4; + g_page_size : integer := 64; + g_num_pages : integer := 2048; + g_num_ports : integer := 18; + g_fifo_size : integer := 4; + g_page_addr_width : integer := 11; + g_partial_select_width : integer := 1 + ); + + port( + -- I/O ports clock (slow) + clk_io_i : in std_logic; + -- Memory/Core clock (fast) + clk_core_i : in std_logic; + + rst_n_io_i : in std_logic; + rst_n_core_i : in std_logic; + +-- read-write ports I/F (streaming) + wport_d_i : in std_logic_vector (g_num_ports * g_data_width -1 downto 0); + wport_dvalid_i : in std_logic_vector (g_num_ports-1 downto 0); + wport_dlast_i : in std_logic_vector (g_num_ports-1 downto 0); + wport_pg_addr_i : in std_logic_vector (g_num_ports * g_page_addr_width -1 downto 0); + wport_pg_req_o : out std_logic_vector(g_num_ports -1 downto 0); + wport_dreq_o : out std_logic_vector (g_num_ports-1 downto 0); + +-- F. B. Memory output + fbm_addr_o : out std_logic_vector(f_log2_size(g_num_pages * g_page_size / g_ratio)-1 downto 0); + fbm_data_o : out std_logic_vector(g_ratio * g_data_width -1 downto 0); + fbm_we_o : out std_logic + ); + +end mpm_write_path; + +architecture rtl of mpm_write_path is + + constant c_line_size_width : integer := f_log2_size(g_page_size / g_ratio); + constant c_fbm_data_width : integer := g_ratio * g_data_width; + constant c_fbm_entries : integer := g_num_pages * g_page_size / g_ratio; + constant c_fbm_addr_width : integer := f_log2_size(c_fbm_entries); + constant c_fifo_sideband_width : integer := c_fbm_addr_width; + + type t_mpm_write_port is record + -- data input + d : std_logic_vector(g_data_width-1 downto 0); + -- 1: got valid data word on d + d_valid : std_logic; + -- 1: end-of-packet + d_last : std_logic; + -- address of the page to be written to (important only on the 1st write to + -- the page) + pg_addr : std_logic_vector(g_page_addr_width-1 downto 0); + pg_req : std_logic; + dreq : std_logic; + end record; + + + type t_wport_state is record + -- clk_io_i domain + pg_addr : unsigned(g_page_addr_width-1 downto 0); + pg_offset : unsigned(c_line_size_width-1 downto 0); + word_count : unsigned(f_log2_size(g_ratio)-1 downto 0); + fbm_addr_in : unsigned(c_fbm_addr_width-1 downto 0); + fifo_full : std_logic; + fifo_we : std_logic; + fifo_align : std_logic; + + -- clk_core_i domain + fifo_rd : std_logic; + fifo_empty : std_logic; + fifo_q : std_logic_vector(c_fbm_data_width -1 downto 0); + fbm_addr_out : std_logic_vector(c_fbm_addr_width-1 downto 0); + grant_d : std_logic_vector(3 downto 0); + end record; + + type t_mpm_write_port_array is array (integer range <>) of t_mpm_write_port; + type t_wport_state_array is array(integer range <>) of t_wport_state; + + signal wstate : t_wport_state_array(g_num_ports-1 downto 0); + signal wport : t_mpm_write_port_array(g_num_ports-1 downto 0); + + + signal arb_req, arb_grant : std_logic_vector(g_num_ports-1 downto 0); + + signal wr_mux_a_in : std_logic_vector(g_num_ports * c_fbm_addr_width -1 downto 0); + signal wr_mux_d_in : std_logic_vector(g_num_ports * c_fbm_data_width -1 downto 0); + signal fbm_we_d : std_logic_vector(2 downto 0); + + signal wr_mux_sel : std_logic_vector(g_num_ports-1 downto 0); + +begin -- rtl + +-- I/O structure serialization/deserialization + gen_serialize_ios : for i in 0 to g_num_ports-1 generate + wport(i).d <= f_slice(wport_d_i, i, g_data_width); + wport(i).d_valid <= wport_dvalid_i(i); + wport(i).d_last <= wport_dlast_i(i); + wport(i).pg_addr <= f_slice(wport_pg_addr_i, i, g_page_addr_width); + wport_dreq_o(i) <= wport(i).dreq; + wport_pg_req_o(i) <= wport(i).pg_req; + end generate gen_serialize_ios; + + ----------------------------------------------------------------------------- + -- Write side logic + ----------------------------------------------------------------------------- + ----------------------------------------------------------------------------- + gen_input_arbiter_ios : for i in 0 to g_num_ports-1 generate + + -- arbiter request vector generation: If there is any data in the input + -- FIFOs, it's request line becomes active. Another requst from the same + -- port can be served 3 cycles later (pipeline delay) + arb_req(i) <= not wstate(i).fifo_empty and not (wstate(i).grant_d(0) or wstate(i).grant_d(1) or wstate(i).grant_d(2)); + + wstate(i).grant_d(0) <= arb_grant(i); + + -- Delay the grant signal to generate enables for each pipeline stage + process(clk_core_i) + begin + if rising_edge(clk_core_i) then + if rst_n_core_i = '0' then + wstate(i).grant_d(3 downto 1) <= (others => '0'); + else + wstate(i).grant_d(3) <= wstate(i).grant_d(2); + wstate(i).grant_d(2) <= wstate(i).grant_d(1); + wstate(i).grant_d(1) <= wstate(i).grant_d(0); + end if; + end if; + end process; + end generate gen_input_arbiter_ios; + + -- The actual round-robin arbiter. + p_input_arbiter : process(clk_core_i) + begin + if rising_edge(clk_core_i) then + if rst_n_core_i = '0' then + arb_grant <= (others => '0'); + else + f_rr_arbitrate(arb_req, arb_grant, arb_grant); + end if; + end if; + end process; + + + + -- write side address counter. Calculates the address of the entry in the F.B. Memory + -- the incoming data shall be written to. + -- It contains two nested counters: + -- - word_count, which counts the number of words in the line of the FBM currently + -- being written. Each line contains g_ratio words of g_data_width. + -- - pg_offset, which counts up every time the previous counter overflow, + -- addressing subsequent cells of the FBM. + -- When we reach the end of the current page, both counters are reset, so we + -- can proceed with the next page. + + gen_input_addr_counters : for i in 0 to g_num_ports-1 generate + process(clk_io_i) + begin + if rising_edge(clk_io_i) then +-- Reset or last data transfer in the frame? Go to the beginning of the page. + if (rst_n_io_i = '0') or (wport(i).d_valid = '1' and wport(i).d_last = '1') then + wstate(i).pg_offset <= (others => '0'); + wstate(i).word_count <= (others => '0'); + else + if(wport(i).d_valid = '1') then + if(wstate(i).word_count = g_ratio-1) then + wstate(i).word_count <= (others => '0'); + + -- end-of-page? + if(wstate(i).pg_offset = g_page_size / g_ratio - 1) then + wstate(i).pg_offset <= (others => '0'); + else + wstate(i).pg_offset <= wstate(i).pg_offset + 1; + end if; + else + wstate(i).word_count <= wstate(i).word_count + 1; + end if; + end if; + end if; + end if; + end process; + + -- Generate a page request signal on the last word of the current page. + -- This way, the source won't have to keep track of the words written per + -- each page and so will save some resources. + wport(i).pg_req <= '1' when (wport(i).d_valid = '1' + and wstate(i).pg_offset = g_page_size/g_ratio-1 + and wstate(i).word_count = g_ratio -1) + else '0'; + + -- combine the current page address and page-internal offset into final + -- FBM address + wstate(i).fbm_addr_in <= resize(unsigned(wport(i).pg_addr) * (g_page_size/g_ratio) + wstate(i).pg_offset, c_fbm_addr_width); + end generate gen_input_addr_counters; + + + -- Input FIFO blocks + gen_input_fifos : for i in 0 to g_num_ports-1 generate + + -- Dual-clock "growing" FIFO. Takes N bit words in clk_io_i clock domain and outputs (N*M) + -- parallelized words in clk_core_i domain. This allows for significant + -- reduction of the size of multipumped memory input registers, but a + -- higher core clock frequency is required. In our case N = g_data_width + -- and M = g_ratio. + -- + -- The FIFO also provides a "sideband" channel working + -- synchronously with the wide port and used to pass FBM addresses. Thanks + -- to that, the fast clock domain only does the multiplexing. + + U_Input_FIFOx : mpm_async_grow_fifo + generic map ( + g_width => g_data_width, + g_ratio => g_ratio, + g_size => g_fifo_size, + g_sideband_width => c_fifo_sideband_width) + port map ( + rst_n_a_i => rst_n_core_i, + clk_wr_i => clk_io_i, + clk_rd_i => clk_core_i, + + we_i => wstate(i).fifo_we, + align_i => wstate(i).fifo_align, + d_i => wport(i).d, + + side_i => std_logic_vector(wstate(i).fbm_addr_in), + side_o => wstate(i).fbm_addr_out, + + rd_i => wstate(i).fifo_rd, + q_o => wstate(i).fifo_q, + full_o => wstate(i).fifo_full, + empty_o => wstate(i).fifo_empty); + + + wport(i).dreq <= not wstate(i).fifo_full; + wstate(i).fifo_we <= wport(i).d_valid; + wstate(i).fifo_align <= wport(i).d_last; + wstate(i).fifo_rd <= wstate(i).grant_d(0); -- and not wstate(i).grant_d(1); + end generate gen_input_fifos; + + + gen_mux_inputs : for i in 0 to g_num_ports-1 generate + wr_mux_d_in(c_fbm_data_width * (i + 1) - 1 downto c_fbm_data_width * i) <= wstate(i).fifo_q; + wr_mux_a_in(c_fbm_addr_width * (i + 1) - 1 downto c_fbm_addr_width * i) <= wstate(i).fbm_addr_out; + wr_mux_sel(i) <= wstate(i).grant_d(1); + end generate gen_mux_inputs; + + U_Data_Mux : mpm_pipelined_mux + generic map ( + g_width => c_fbm_data_width, + g_inputs => g_num_ports) + port map ( + clk_i => clk_core_i, + rst_n_i => rst_n_core_i, + d_i => wr_mux_d_in, + q_o => fbm_data_o, + sel_i => wr_mux_sel); + + U_WR_Address_Mux : mpm_pipelined_mux + generic map ( + g_width => c_fbm_addr_width, + g_inputs => g_num_ports) + port map ( + clk_i => clk_core_i, + rst_n_i => rst_n_core_i, + d_i => wr_mux_a_in, + q_o => fbm_addr_o, + sel_i => wr_mux_sel); + + + p_write_pipe : process(clk_core_i) + begin + if rising_edge(clk_core_i) then + if rst_n_core_i = '0' then + fbm_we_d <= (others => '0'); + else + if(unsigned(wr_mux_sel) /= 0) then + fbm_we_d(0) <= '1'; + else + fbm_we_d(0) <= '0'; + end if; + fbm_we_d(1) <= fbm_we_d(0); + fbm_we_d(2) <= fbm_we_d(1); + end if; + end if; + end process; + + + fbm_we_o <= fbm_we_d(1); + + +end rtl; diff --git a/modules/wrsw_swcore/async/swc_async_fifo.vhd b/modules/wrsw_swcore/async/swc_async_fifo.vhd deleted file mode 100644 index 3ec9c39f..00000000 --- a/modules/wrsw_swcore/async/swc_async_fifo.vhd +++ /dev/null @@ -1,106 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.genram_pkg.all; -- for f_log2_size - -entity swc_async_grow_fifo is - - generic ( - g_width : integer; - g_ratio : integer; - g_size : integer); - - port ( - rst_n_i : in std_logic; - clk_wr_i : in std_logic; - clk_rd_i : in std_logic; - - we_i : in std_logic; - d_i : in std_logic_vector(g_width-1 downto 0); - - rd_i : in std_logic; - q_o : out std_logic_vector(g_width * g_ratio-1 downto 0); - - wr_full_o : out std_logic; - rd_empty_o : out std_logic); - -end swc_async_grow_fifo; - -architecture rtl of swc_async_grow_fifo is - - component swc_fifo_mem_cell - generic ( - g_width : integer; - g_size : integer); - port ( - clk_i : in std_logic; - wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); - wd_i : in std_logic_vector(g_width-1 downto 0); - we_i : in std_logic; - ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); - rd_o : out std_logic_vector(g_width-1 downto 0)); - end component; - - component swc_async_fifo_ctrl - generic ( - g_size : integer); - port ( - rst_n_i : in std_logic; - clk_wr_i : in std_logic; - clk_rd_i : in std_logic; - rd_i : in std_logic; - wr_i : in std_logic; - wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); - rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); - full_o : out std_logic; - empty_o : out std_logic); - end component; - - signal wr_sreg : std_logic_vector(g_ratio-1 downto 0); - signal wr_cell : std_logic_vector(g_ratio-1 downto 0); - signal real_we : std_logic; - signal q_int : std_logic_vector(g_width*g_ratio-1 downto 0); - signal wr_addr, rd_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0); - -begin -- rtl - - gen_mem_cells : for i in 0 to g_ratio-1 generate - - wr_cell(i) <= we_i and wr_sreg(i); - U_Mem : swc_fifo_mem_cell - generic map ( - g_width => g_width * g_ratio, - g_size => g_size) - port map ( - clk_i => clk_wr_i, - wa_i => wr_addr, - wd_i => d_i, - we_i => rd_addr, - ra_i => std_logic_vector(rd_ptr), - rd_o => q_int(g_width*(i+1) -1 downto g_width*i)); - end generate gen_mem_cells; - - p_write_grow_sreg : process(clk_wr_i, rst_n_i) - begin - if rst_n_i = '0' then - wr_sreg(0) <= '1'; - wr_sreg(wr_sreg'left downto 1) <= (others => '0'); - real_we <= '0'; - elsif rising_edge(clk_wr_i) then - if(we_i = '1') then - wr_sreg <= wr_sreg(wr_sreg'left-1 downto 0) & wr_sreg(wr_sreg'left); - - if(wr_sreg(wr_sreg'left) = '1' and full_int = '0') then - real_we <= '1'; - else - real_we <= '0'; - end if; - else - real_we <= '0'; - end if; - end if; - end process; - - -end rtl; diff --git a/modules/wrsw_swcore/async/swc_async_fifo_ctrl.vhd b/modules/wrsw_swcore/async/swc_async_fifo_ctrl.vhd deleted file mode 100644 index 9ceed766..00000000 --- a/modules/wrsw_swcore/async/swc_async_fifo_ctrl.vhd +++ /dev/null @@ -1,164 +0,0 @@ -------------------------------------------------------------------------------- --- Title : Dual clock (asynchronous) FIFO controller --- Project : White Rabbit Switch -------------------------------------------------------------------------------- --- File : swc_async_fifo_ctrl.vhd --- Author : Tomasz WÅ‚ostowski --- Company : CERN BE-CO-HT --- Created : 2012-01-30 --- Last update : 2012-01-30 --- Platform : FPGA-generic --- Standard : VHDL'93 --- Dependencies : genram_pkg -------------------------------------------------------------------------------- --- Description: Gray-encoded dual clock FIFO controller and address generator. --- Based on Xilinx Application Note "Asynchronous FIFO in Virtex-II FPGAs" by --- P. Alfke & example code from http://www.asic-world.com. -------------------------------------------------------------------------------- --- --- Copyright (c) 2012 CERN --- --- This source file is free software; you can redistribute it --- and/or modify it under the terms of the GNU Lesser General --- Public License as published by the Free Software Foundation; --- either version 2.1 of the License, or (at your option) any --- later version. --- --- This source is distributed in the hope that it will be --- useful, but WITHOUT ANY WARRANTY; without even the implied --- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR --- PURPOSE. See the GNU Lesser General Public License for more --- details. --- --- You should have received a copy of the GNU Lesser General --- Public License along with this source; if not, download it --- from http://www.gnu.org/licenses/lgpl-2.1.html --- -------------------------------------------------------------------------------- --- Revisions : --- Date Version Author Description --- 2012-01-30 1.0 twlostow Created -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.genram_pkg.all; - -entity swc_async_fifo_ctrl is - - generic ( - g_size : integer); - - port( - rst_n_a_i : in std_logic; - clk_wr_i : in std_logic; - clk_rd_i : in std_logic; - - rd_i : in std_logic; - wr_i : in std_logic; - - wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); - rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); - - full_o : out std_logic; - empty_o : out std_logic); - -end swc_async_fifo_ctrl; - -architecture rtl of swc_async_fifo_ctrl is - - -- Gray-encoded increase-by-1 function. Takes a gray-encoded integer x and returns - -- gray-encoded value of (x+1). - function f_gray_inc(x : unsigned) return unsigned is - variable bin, tmp : unsigned(x'left downto 0); - begin - -- gray to binary - for i in 0 to x'left loop - bin(i) := '0'; - for j in i to x'left loop - bin(i) := bin(i) xor x(j); - end loop; -- j - end loop; -- i - -- increase - tmp := bin + 1; - -- binary to gray - return tmp(tmp'left) & (tmp(tmp'left-1 downto 0) xor tmp(tmp'left downto 1)); - end f_gray_inc; - - signal wr_ptr, rd_ptr : unsigned(f_log2_size(g_size) -1 downto 0); - signal full_int, empty_int : std_logic; - signal same_addr : std_logic; - signal rst_stat, set_stat : std_logic; - signal set_full, set_empty : std_logic; - signal stat : std_logic; -begin -- rtl - - p_write_ptr : process(clk_wr_i, rst_n_a_i) - begin - if rst_n_a_i = '0' then - wr_ptr <= (others => '0'); - elsif rising_edge(clk_wr_i) then - if(wr_i = '1' and full_int = '0') then - wr_ptr <= f_gray_inc(wr_ptr); - end if; - end if; - end process; - - - p_read_ptr : process(clk_rd_i, rst_n_a_i) - begin - if rst_n_a_i = '0' then - rd_ptr <= (others => '0'); - elsif rising_edge(clk_rd_i) then - if(rd_i = '1' and empty_int = '0') then - rd_ptr <= f_gray_inc(rd_ptr); - end if; - end if; - end process; - - p_quardant_status : process(rd_ptr, wr_ptr) - begin - set_stat <= (wr_ptr(wr_ptr'left-1) xnor rd_ptr(rd_ptr'left)) - and (wr_ptr(wr_ptr'left) xor rd_ptr(rd_ptr'left-1)); - rst_stat <= (wr_ptr(wr_ptr'left-1) xor rd_ptr(rd_ptr'left)) - and (wr_ptr(wr_ptr'left) xnor rd_ptr(rd_ptr'left-1)); - end process; - - process(set_stat, rst_stat, rst_n_a_i) - begin - if(rst_stat = '1' or rst_n_a_i = '0') then - stat <= '0'; - elsif(set_stat = '1') then - stat <= '1'; - end if; - end process; - - set_full <= '1' when (stat = '1' and wr_ptr = rd_ptr) else '0'; - set_empty <= '1' when (stat = '0' and wr_ptr = rd_ptr) else '0'; - - p_full_flag : process(clk_wr_i, set_full) - begin - if(set_full = '1') then - full_int <= '1'; - elsif rising_edge(clk_wr_i) then - full_int <= set_full; - end if; - end process; - - p_empty_flag : process(clk_rd_i, set_empty) - begin - if(set_empty = '1') then - empty_int <= '1'; - elsif rising_edge(clk_rd_i) then - empty_int <= set_empty; - end if; - end process; - - full_o <= full_int; - empty_o <= empty_int; - - wr_addr_o <= std_logic_vector(wr_ptr); - rd_addr_o <= std_logic_vector(rd_ptr); -end rtl; diff --git a/modules/wrsw_swcore/async/swc_async_grow_fifo.vhd b/modules/wrsw_swcore/async/swc_async_grow_fifo.vhd deleted file mode 100644 index 613fe465..00000000 --- a/modules/wrsw_swcore/async/swc_async_grow_fifo.vhd +++ /dev/null @@ -1,138 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.genram_pkg.all; -- for f_log2_size - -entity swc_async_grow_fifo is - - generic ( - g_width : integer := 16; - g_ratio : integer := 6; - g_size : integer := 8; - g_sideband_width : integer := 16); - - port ( - rst_n_i : in std_logic; - clk_wr_i : in std_logic; - clk_rd_i : in std_logic; - - we_i : in std_logic; - align_i : in std_logic; -- 1: aligned write - d_i : in std_logic_vector(g_width-1 downto 0); - - rd_i : in std_logic; - q_o : out std_logic_vector(g_width * g_ratio-1 downto 0); - - -- "Sideband" channel (for passing aux data) - side_i : in std_logic_vector(g_sideband_width-1 downto 0); - side_o : out std_logic_vector(g_sideband_width-1 downto 0); - - full_o : out std_logic; - empty_o : out std_logic); - -end swc_async_grow_fifo; - -architecture rtl of swc_async_grow_fifo is - - component swc_fifo_mem_cell - generic ( - g_width : integer; - g_size : integer); - port ( - clk_i : in std_logic; - wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); - wd_i : in std_logic_vector(g_width-1 downto 0); - we_i : in std_logic; - ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); - rd_o : out std_logic_vector(g_width-1 downto 0)); - end component; - - component swc_async_fifo_ctrl - generic ( - g_size : integer); - port ( - rst_n_i : in std_logic; - clk_wr_i : in std_logic; - clk_rd_i : in std_logic; - rd_i : in std_logic; - wr_i : in std_logic; - wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); - rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); - full_o : out std_logic; - empty_o : out std_logic); - end component; - - signal wr_sreg : std_logic_vector(g_ratio-1 downto 0); - signal wr_cell : std_logic_vector(g_ratio-1 downto 0); - signal real_we : std_logic; - signal q_int : std_logic_vector(g_width*g_ratio-1 downto 0); - signal wr_addr, rd_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0); - signal full_int : std_logic; - -begin -- rtl - - gen_mem_cells : for i in 0 to g_ratio-1 generate - - wr_cell(i) <= wr_sreg(i) and we_i; - - U_Mem : swc_fifo_mem_cell - generic map ( - g_width => g_width, - g_size => g_size) - port map ( - clk_i => clk_wr_i, - wa_i => wr_addr, - wd_i => d_i, - we_i => wr_cell(i), - ra_i => rd_addr, - rd_o => q_int(g_width*(i+1) -1 downto g_width*i)); - end generate gen_mem_cells; - - U_CTRL : swc_async_fifo_ctrl - generic map ( - g_size => g_size) - port map ( - rst_n_i => rst_n_i, - clk_wr_i => clk_wr_i, - clk_rd_i => clk_rd_i, - rd_i => rd_i, - wr_i => real_we, - wr_addr_o => wr_addr, - rd_addr_o => rd_addr, - full_o => full_int, - empty_o => empty_o); - - p_write_grow_sreg : process(clk_wr_i, rst_n_i) - begin - if rst_n_i = '0' then - wr_sreg(0) <= '1'; - wr_sreg(wr_sreg'left downto 1) <= (others => '0'); - elsif rising_edge(clk_wr_i) then - if(we_i = '1') then - if(align_i = '1') then - wr_sreg(0) <= '1'; - wr_sreg(wr_sreg'left downto 1) <= (others => '0'); - else - wr_sreg <= wr_sreg(wr_sreg'left-1 downto 0) & wr_sreg(wr_sreg'left); - end if; - end if; - end if; - end process; - - real_we <= wr_cell(wr_cell'left); - - p_output_reg : process(clk_rd_i, rst_n_i) - begin - if (rst_n_i = '0') then - q_o <= (others => '0'); - elsif rising_edge(clk_rd_i) then - if(rd_i = '1') then - q_o <= q_int; - end if; - end if; - end process; - - full_o <= full_int and wr_sreg(wr_sreg'left); - -end rtl; diff --git a/modules/wrsw_swcore/async/swc_async_multiport_mem.vhd b/modules/wrsw_swcore/async/swc_async_multiport_mem.vhd deleted file mode 100644 index 10d6d3f4..00000000 --- a/modules/wrsw_swcore/async/swc_async_multiport_mem.vhd +++ /dev/null @@ -1,139 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.swc_private_pkg.all; -use work.genram_pkg.all; - -entity swc_async_multiport_mem is - - generic ( - g_ratio : integer; - g_page_size : integer; - g_num_pages : integer; - g_num_ports : integer - ); - - port( - -- I/O ports clock (slow) - clk_io_i : in std_logic; - -- Memory/Core clock (fast) - clk_core_i : in std_logic; - rst_n_i : in std_logic; - --- read-write ports I/F (streaming) - wport_i : in t_mpm_write_in_array(0 to g_num_ports-1); - wport_o : out t_mpm_write_out_array(0 to g_num_ports-1); - - rport_i : in t_mpm_read_in_array(0 to g_num_ports-1); - rport_o : out t_mpm_read_out_array(0 to g_num_ports-1); - --- linked list I/F - - ll_addr_o : out std_logic_vector(f_log2_size(g_num_pages)-1 downto 0); - ll_data_o : out std_logic_vector(f_log2_size(g_num_pages)-1 downto 0); - ll_data_i : in std_logic_vector(f_log2_size(g_num_pages)-1 downto 0); - ll_we_o : out std_logic - ); - -end swc_async_multiport_mem; - -architecture rtl of swc_async_multiport_mem is - - - component swc_async_grow_fifo - generic ( - g_width : integer; - g_ratio : integer; - g_size : integer); - port ( - rst_n_i : in std_logic; - clk_wr_i : in std_logic; - clk_rd_i : in std_logic; - align_i : in std_logic; - we_i : in std_logic; - d_i : in std_logic_vector(g_width-1 downto 0); - rd_i : in std_logic; - q_o : out std_logic_vector(g_width * g_ratio-1 downto 0); - full_o : out std_logic; - empty_o : out std_logic); - end component; - - type t_fifo_slv_array is array(0 to g_num_ports-1) of std_logic_vector(c_data_path_width downto 0); - - type t_wport_state is record - cur_page : unsigned(c_page_addr_width-1 downto 0); - cur_offset : unsigned(f_log2_size(g_page_size)-1 downto 0); - cur_valid : std_logic; - next_page : unsigned(c_page_addr_width-1 downto 0); - next_offset : unsigned(f_log2_size(g_page_size)-1 downto 0); - next_valid : std_logic; - - fifo_empty : std_logic; - fifo_full : std_logic; - fifo_nempty : std_logic; - fifo_rd : std_logic; - fifo_q : std_logic_vector((c_data_path_width+1) * g_ratio - 1 downto 0); - end record; - - type t_wport_state_array is array(0 to g_num_ports-1) of t_wport_state; - - signal w_req, w_sel, w_mask : std_logic_vector(f_log2_size(g_num_ports)-1 downto 0); - signal wstate : t_wport_state_array; - - procedure f_rr_arbitrate ( - signal req : in std_logic_vector; - signal pre_grant : in std_logic_vector; - signal grant : out std_logic_vector)is - - variable reqs : std_logic_vector(g_width - 1 downto 0); - variable gnts : std_logic_vector(g_width - 1 downto 0); - variable gnt : std_logic_vector(g_width - 1 downto 0); - variable gntM : std_logic_vector(g_width - 1 downto 0); - variable zeros : std_logic_vector(g_width - 1 downto 0); - - begin - zeros := (others => '0'); - - -- bit twiddling magic : - s_gnt := req and std_logic_vector(unsigned(not req) + 1); - s_reqs := req and not (std_logic_vector(unsigned(pre_grant) - 1) or pre_grant); - s_gnts := reqs and std_logic_vector(unsigned(not reqs)+1); - s_gntM := gnt when reqs = zeros else gnts; - - if((req and pre_grant) = s_zeros) then - grant <= gntM; - s_pre_grant <= gntM; -- remember current grant vector, for the next operation - end if; - - end f_rr_arbitrate; - - -begin -- rtl - - gen_input_fifos : for i in 0 to g_num_ports-1 generate - - U_Input_FIFOx : swc_async_grow_fifo - generic map ( - g_width => c_data_path_width + 1, - g_ratio => g_ratio, - g_size => c_mpm_async_fifo_depth) - port map ( - rst_n_i => rst_n_i, - clk_wr_i => clk_io_i, - clk_rd_i => clk_core_i, - we_i => wport_i(i).d_valid, - d_i(c_data_path_width-2 downto 0) => wport_i(i).d, - d_i(c_data_path_width-1) => wport_i(i).d_eof, - align_i => wport_i(i).d_eof, - - rd_i => wstate(i).fifo_rd, - q_o => wstate(i).fifo_q, - full_o => wstate(i).fifo_full, - empty_o => wstate(i).fifo_empty); - end generate gen_input_fifos; - - - - -end rtl; diff --git a/modules/wrsw_swcore/async/swc_async_shrink_fifo.vhd b/modules/wrsw_swcore/async/swc_async_shrink_fifo.vhd deleted file mode 100644 index 8ee4f9a3..00000000 --- a/modules/wrsw_swcore/async/swc_async_shrink_fifo.vhd +++ /dev/null @@ -1,122 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.genram_pkg.all; -- for f_log2_size - -entity swc_async_shrink_fifo is - - generic ( - g_width : integer; -- narrow port width - g_ratio : integer; - g_size : integer); - - port ( - rst_n_i : in std_logic; - clk_wr_i : in std_logic; - clk_rd_i : in std_logic; - - we_i : in std_logic; - d_i : in std_logic_vector(g_width*g_ratio-1 downto 0); - - rd_i : in std_logic; - q_o : out std_logic_vector(g_width-1 downto 0); - - full_o : out std_logic; - empty_o : out std_logic); - -end swc_async_shrink_fifo; - -architecture rtl of swc_async_shrink_fifo is - - component swc_fifo_mem_cell - generic ( - g_width : integer; - g_size : integer); - port ( - clk_i : in std_logic; - wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); - wd_i : in std_logic_vector(g_width-1 downto 0); - we_i : in std_logic; - ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); - rd_o : out std_logic_vector(g_width-1 downto 0)); - end component; - - component swc_async_fifo_ctrl - generic ( - g_size : integer); - port ( - rst_n_i : in std_logic; - clk_wr_i : in std_logic; - clk_rd_i : in std_logic; - rd_i : in std_logic; - wr_i : in std_logic; - wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); - rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); - full_o : out std_logic; - empty_o : out std_logic); - end component; - - signal rd_count : unsigned(3 downto 0); - signal real_rd : std_logic; - signal q_int : std_logic_vector(g_width*g_ratio-1 downto 0); - signal wr_addr, rd_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0); - signal empty_int : std_logic; - signal line_flushed : std_logic; -begin -- rtl - - gen_mem_cells : for i in 0 to g_ratio-1 generate - - U_Mem : swc_fifo_mem_cell - generic map ( - g_width => g_width, - g_size => g_size) - port map ( - clk_i => clk_wr_i, - wa_i => wr_addr, - wd_i => d_i(g_width*(i+1) -1 downto g_width*i), - we_i => we_i, - ra_i => rd_addr, - rd_o => q_int(g_width*(i+1) -1 downto g_width*i)); - end generate gen_mem_cells; - - U_CTRL : swc_async_fifo_ctrl - generic map ( - g_size => g_size) - port map ( - rst_n_i => rst_n_i, - clk_wr_i => clk_wr_i, - clk_rd_i => clk_rd_i, - rd_i => real_rd, - wr_i => we_i, - wr_addr_o => wr_addr, - rd_addr_o => rd_addr, - full_o => full_o, - empty_o => empty_int); - - p_read_mux : process(clk_rd_i, rst_n_i) - begin - if rst_n_i = '0' then - rd_count <= (others => '0'); - q_o <= (others => '0'); - elsif rising_edge(clk_rd_i) then - if(rd_i = '1' and empty_int = '0') then - if(rd_count = g_ratio-1) then - rd_count <= (others => '0'); - else - rd_count <= rd_count + 1; - end if; - - q_o <= q_int(((to_integer(rd_count)+1)*g_width)-1 downto to_integer(rd_count)*g_width); - end if; - - end if; - end process; - - - line_flushed <= '1' when (rd_count = g_ratio-1) else '0'; - real_rd <= line_flushed and rd_i; - - empty_o <= empty_int and line_flushed; - -end rtl; diff --git a/modules/wrsw_swcore/async/swc_private_pkg.vhd b/modules/wrsw_swcore/async/swc_private_pkg.vhd deleted file mode 100644 index 1467c278..00000000 --- a/modules/wrsw_swcore/async/swc_private_pkg.vhd +++ /dev/null @@ -1,50 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; - -package swc_private_pkg is - - constant c_data_path_width : integer := 18; - constant c_eof_marker : std_logic_vector(c_data_path_width-1 downto 0) := "11XXXXXXXXXXXXXXXX"; - constant c_mpm_async_fifo_depth : integer := 8; - constant c_page_addr_width : integer := 12; - - type t_generic_slv_array is array (integer range <>, integer range <>) of std_logic; - - type t_mpm_write_in is record - d : std_logic_vector(c_data_path_width-1 downto 0); - d_valid : std_logic; - d_eof : std_logic; - pg_addr : std_logic_vector(c_page_addr_width-1 downto 0); - pg_valid : std_logic; - end record; - - type t_mpm_write_out is record - d_req : std_logic; - pg_req : std_logic; - end record; - - type t_mpm_write_in_array is array (integer range <>) of t_mpm_write_in; - type t_mpm_write_out_array is array (integer range <>) of t_mpm_write_out; - - - type t_mpm_read_out is record - d : std_logic_vector(c_data_path_width-1 downto 0); - d_valid : std_logic; - d_eof : std_logic; - pg_req : std_logic; - end record; - - type t_mpm_read_in is record - pg_addr : std_logic_vector(c_page_addr_width-1 downto 0); - pg_valid : std_logic; - d_req : std_logic; - end record; - - type t_mpm_read_in_array is array (integer range <>) of t_mpm_read_in; - type t_mpm_read_out_array is array (integer range <>) of t_mpm_read_out; - - - - - -end swc_private_pkg; diff --git a/modules/wrsw_swcore/async/swc_swcore_pkg.vhd b/modules/wrsw_swcore/async/swc_swcore_pkg.vhd deleted file mode 100644 index b20c8917..00000000 --- a/modules/wrsw_swcore/async/swc_swcore_pkg.vhd +++ /dev/null @@ -1,540 +0,0 @@ -------------------------------------------------------------------------------- --- Title : Switching Core Package --- Project : WhiteRabbit switch -------------------------------------------------------------------------------- --- File : swc_swcore_pkg.vhd --- Author : Tomasz Wlostowski --- Company : CERN BE-Co-HT --- Created : 2010-04-08 --- Last update: 2011-12-15 --- Platform : FPGA-generic --- Standard : VHDL'87 -------------------------------------------------------------------------------- --- Description: -------------------------------------------------------------------------------- --- --- Copyright (c) 2010 Tomasz Wlostowski, Maciej Lipinski / CERN --- --- This source file is free software; you can redistribute it --- and/or modify it under the terms of the GNU Lesser General --- Public License as published by the Free Software Foundation; --- either version 2.1 of the License, or (at your option) any --- later version. --- --- This source is distributed in the hope that it will be --- useful, but WITHOUT ANY WARRANTY; without even the implied --- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR --- PURPOSE. See the GNU Lesser General Public License for more --- details. --- --- You should have received a copy of the GNU Lesser General --- Public License along with this source; if not, download it --- from http://www.gnu.org/licenses/lgpl-2.1.html --- -------------------------------------------------------------------------------- --- Revisions : --- Date Version Author Description --- 2010-04-08 1.0 twlostow Created --- 2010-11-22 2.0 mlipinsk added staff -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.math_real.CEIL; -use ieee.math_real.log2; - -package swc_swcore_pkg is - - type t_swcore_gen_parameters is record - num_ports: integer; - mem_pages: integer; - page_size: integer; - - end record; - - --- number of switch ports - constant c_swc_num_ports : integer := 11; --- size of the packet memory in words (1 word = 1 ctrl + data sequence) - constant c_swc_packet_mem_size : integer := 65536; - - constant c_swc_packet_mem_multiply : integer := 16; - constant c_swc_data_width : integer := 16; - constant c_swc_ctrl_width : integer := 4; --16; - constant c_swc_page_size : integer := 64; - - - constant c_swc_output_prio_num : integer := 8; - - constant c_swc_max_pck_size : integer := 10 * 1024; -- 10 kB - - - -- - constant c_swc_input_fifo_size : integer := 2 * c_swc_packet_mem_multiply; - constant c_swc_input_fifo_size_log2 : integer := integer(CEIL(LOG2(real(c_swc_input_fifo_size - 1)))); - constant c_swc_fifo_full_in_advance : integer := c_swc_input_fifo_size - 3; - - constant c_swc_num_ports_width : integer := integer(CEIL(LOG2(real(c_swc_num_ports-1)))); - constant c_swc_packet_mem_num_pages : integer := (c_swc_packet_mem_size / c_swc_page_size); -- 65536/64 = 1024 - - constant c_swc_output_fifo_size : integer := 64; --old value: 16; - - constant c_swc_freeing_fifo_size : integer := (c_swc_packet_mem_num_pages/2); - constant c_swc_freeing_fifo_log2 : integer := integer(CEIL(LOG2(real(c_swc_freeing_fifo_size-1)))); - - constant c_swc_page_addr_width : integer := integer(CEIL(LOG2(real(c_swc_packet_mem_num_pages-1)))); - constant c_swc_usecount_width : integer := integer(CEIL(LOG2(real(c_swc_num_ports-1)))); - constant c_swc_page_offset_width : integer := integer(CEIL(LOG2(real(c_swc_page_size / c_swc_packet_mem_multiply)))); - constant c_swc_packet_mem_addr_width : integer := c_swc_page_addr_width + c_swc_page_offset_width; - constant c_swc_pump_width : integer := c_swc_data_width + c_swc_ctrl_width; - - constant c_swc_output_fifo_addr_width : integer := integer(CEIL(LOG2(real(c_swc_output_fifo_size-1)))); - constant c_swc_output_prio_num_width : integer := integer(CEIL(LOG2(real(c_swc_output_prio_num -1)))); - - constant c_swc_max_pck_size_width : integer := integer(CEIL(LOG2(real(c_swc_max_pck_size -1))));-- 14 bits - - -- TODO: probably need later to use the global constant - constant c_swc_prio_width : integer := 3; - - type t_slv_array is array(integer range <>, integer range <>) of std_logic; - --- type declarations for memory input/output registers in data pump - subtype t_pump_entry is std_logic_vector(c_swc_pump_width-1 downto 0); - type t_pump_reg is array (c_swc_packet_mem_multiply-1 downto 0) of t_pump_entry; - - component swc_prio_encoder - generic ( - g_num_inputs : integer range 2 to 64; - g_output_bits : integer range 1 to 6); - port ( - in_i : in std_logic_vector(g_num_inputs-1 downto 0); - out_o : out std_logic_vector(g_output_bits-1 downto 0); - onehot_o : out std_logic_vector(g_num_inputs-1 downto 0); - mask_o : out std_logic_vector(g_num_inputs-1 downto 0); - zero_o : out std_logic); - end component; - - component swc_page_allocator - generic ( - g_num_pages : integer; - g_page_addr_bits : integer; - g_use_count_bits : integer); - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - alloc_i : in std_logic; - free_i : in std_logic; - force_free_i : in std_logic; - set_usecnt_i : in std_logic; - usecnt_i : in std_logic_vector(g_use_count_bits-1 downto 0); - pgaddr_i : in std_logic_vector(g_page_addr_bits -1 downto 0); - pgaddr_o : out std_logic_vector(g_page_addr_bits -1 downto 0); - pgaddr_valid_o : out std_logic; - idle_o : out std_logic; - done_o : out std_logic; - nomem_o : out std_logic); - end component; - - component swc_rr_arbiter - generic ( - g_num_ports : natural; - g_num_ports_log2 : natural); - port ( - rst_n_i : in std_logic; - clk_i : in std_logic; - next_i : in std_logic; - request_i : in std_logic_vector(g_num_ports -1 downto 0); - grant_o : out std_logic_vector(g_num_ports_log2 - 1 downto 0); - grant_valid_o : out std_logic); - end component; - - component swc_packet_mem_write_pump - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - pgaddr_i : in std_logic_vector(c_swc_page_addr_width-1 downto 0); - pgreq_i : in std_logic; - pgend_o : out std_logic; - pckstart_i : in std_logic; - drdy_i : in std_logic; - full_o : out std_logic; - flush_i : in std_logic; - ll_addr_o : out std_logic_vector(c_swc_page_addr_width -1 downto 0); - ll_data_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0); - ll_wr_req_o : out std_logic; - ll_wr_done_i : in std_logic; - sync_i : in std_logic; - addr_o : out std_logic_vector(c_swc_packet_mem_addr_width -1 downto 0); - d_i : in std_logic_vector(c_swc_pump_width -1 downto 0); - q_o : out std_logic_vector(c_swc_pump_width * c_swc_packet_mem_multiply - 1 downto 0); - we_o : out std_logic); - end component; - - component swc_packet_mem_read_pump - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - pgreq_i : in std_logic; - pgaddr_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - pgend_o : out std_logic; - pckend_o : out std_logic; - drdy_o : out std_logic; - dreq_i : in std_logic; - sync_read_i : in std_logic; - ll_read_addr_o : out std_logic_vector(c_swc_page_addr_width -1 downto 0); - ll_read_data_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - ll_read_req_o : out std_logic; - ll_read_valid_data_i: in std_logic; - sync_i : in std_logic; - d_o : out std_logic_vector(c_swc_pump_width - 1 downto 0); - addr_o : out std_logic_vector(c_swc_packet_mem_addr_width - 1 downto 0); - q_i : in std_logic_vector(c_swc_pump_width * c_swc_packet_mem_multiply -1 downto 0)); - end component; - - component swc_multiport_linked_list is - port ( - rst_n_i : in std_logic; - clk_i : in std_logic; - - write_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - write_done_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - write_addr_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - write_data_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - - - free_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - free_done_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - free_addr_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - - - read_pump_read_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - read_pump_read_done_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - read_pump_addr_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - - free_pck_read_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - free_pck_read_done_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - free_pck_addr_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - - data_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0) - ); - - end component; - - component swc_input_block is - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - ------------------------------------------------------------------------------- - -- Fabric I/F - ------------------------------------------------------------------------------ - tx_sof_p1_i : in std_logic; - tx_eof_p1_i : in std_logic; - tx_data_i : in std_logic_vector(c_swc_data_width - 1 downto 0); - tx_ctrl_i : in std_logic_vector(c_swc_ctrl_width - 1 downto 0); - tx_valid_i : in std_logic; - tx_bytesel_i : in std_logic; - tx_dreq_o : out std_logic; - tx_abort_p1_i : in std_logic; - tx_rerror_p1_i : in std_logic; - ------------------------------------------------------------------------------- - -- I/F with Page allocator (MMU) - ------------------------------------------------------------------------------- - mmu_page_alloc_req_o : out std_logic; - mmu_page_alloc_done_i : in std_logic; - mmu_pageaddr_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - mmu_pageaddr_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0); - mmu_force_free_o : out std_logic; - mmu_force_free_done_i : in std_logic; - mmu_force_free_addr_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0); - mmu_set_usecnt_o : out std_logic; - mmu_set_usecnt_done_i : in std_logic; - mmu_usecnt_o : out std_logic_vector(c_swc_usecount_width - 1 downto 0); - mmu_nomem_i : in std_logic; - ------------------------------------------------------------------------------- - -- I/F with Routing Table Unit (RTU) - ------------------------------------------------------------------------------- - rtu_rsp_valid_i : in std_logic; - rtu_rsp_ack_o : out std_logic; - rtu_dst_port_mask_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - rtu_drop_i : in std_logic; - rtu_prio_i : in std_logic_vector(c_swc_prio_width - 1 downto 0); - ------------------------------------------------------------------------------- - -- I/F with Multiport Memory (MPU) - ------------------------------------------------------------------------------- - mpm_pckstart_o : out std_logic; - mpm_pageaddr_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0); - mpm_pagereq_o : out std_logic; - mpm_pageend_i : in std_logic; - mpm_data_o : out std_logic_vector(c_swc_data_width - 1 downto 0); - mpm_ctrl_o : out std_logic_vector(c_swc_ctrl_width - 1 downto 0); - mpm_drdy_o : out std_logic; - mpm_full_i : in std_logic; - mpm_flush_o : out std_logic; - mpm_wr_sync_i : in std_logic; - ------------------------------------------------------------------------------- - -- I/F with Page Transfer Arbiter (PTA) - ------------------------------------------------------------------------------- - pta_transfer_pck_o : out std_logic; - pta_transfer_ack_i : in std_logic; - pta_pageaddr_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0); - pta_mask_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - pta_pck_size_o : out std_logic_vector(c_swc_max_pck_size_width - 1 downto 0); - pta_prio_o : out std_logic_vector(c_swc_prio_width - 1 downto 0) - - ); - end component; - - - component swc_multiport_page_allocator is - port ( - rst_n_i : in std_logic; - clk_i : in std_logic; - alloc_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - free_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - force_free_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - set_usecnt_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - alloc_done_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - free_done_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - force_free_done_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - set_usecnt_done_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - pgaddr_free_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - pgaddr_force_free_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - pgaddr_usecnt_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - usecnt_i : in std_logic_vector(c_swc_num_ports * c_swc_usecount_width - 1 downto 0); - pgaddr_alloc_o : out std_logic_vector(c_swc_page_addr_width-1 downto 0); - nomem_o : out std_logic - ); - - end component; - - component swc_packet_mem is - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - ------------------- writing to the shared memory -------------------------- - wr_pagereq_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - wr_pckstart_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - wr_pageaddr_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - wr_pageend_o : out std_logic_vector(c_swc_num_ports -1 downto 0); - wr_ctrl_i : in std_logic_vector(c_swc_num_ports * c_swc_ctrl_width - 1 downto 0); - wr_data_i : in std_logic_vector(c_swc_num_ports * c_swc_data_width - 1 downto 0); - wr_drdy_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - wr_full_o : out std_logic_vector(c_swc_num_ports-1 downto 0); - wr_flush_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - wr_sync_o : out std_logic_vector(c_swc_num_ports -1 downto 0); - ------------------- reading from the shared memory -------------------------- - rd_pagereq_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - rd_pageaddr_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - rd_pageend_o : out std_logic_vector(c_swc_num_ports -1 downto 0); - rd_pckend_o : out std_logic_vector(c_swc_num_ports-1 downto 0); - rd_drdy_o : out std_logic_vector(c_swc_num_ports -1 downto 0); - rd_dreq_i : in std_logic_vector(c_swc_num_ports -1 downto 0); - rd_sync_read_i : in std_logic_vector(c_swc_num_ports -1 downto 0); - rd_data_o : out std_logic_vector(c_swc_num_ports * c_swc_data_width - 1 downto 0); - rd_ctrl_o : out std_logic_vector(c_swc_num_ports * c_swc_ctrl_width - 1 downto 0); - rd_sync_o : out std_logic_vector(c_swc_num_ports -1 downto 0); --- pa_free_o : out std_logic_vector(c_swc_num_ports -1 downto 0); --- pa_free_done_i : in std_logic_vector(c_swc_num_ports -1 downto 0); --- pa_free_pgaddr_o : out std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - - write_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - write_done_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - write_addr_o : out std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - write_data_o : out std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - read_pump_read_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - read_pump_read_done_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - read_pump_addr_o : out std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - data_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0) - ); - - end component; - - - component swc_pck_transfer_input is - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - - pto_transfer_pck_o : out std_logic; - pto_pageaddr_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0); - pto_output_mask_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - pto_read_mask_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - pto_prio_o : out std_logic_vector(c_swc_prio_width - 1 downto 0); - pto_pck_size_o : out std_logic_vector(c_swc_max_pck_size_width - 1 downto 0); - - ib_transfer_pck_i : in std_logic; - ib_pageaddr_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - ib_mask_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - ib_prio_i : in std_logic_vector(c_swc_prio_width - 1 downto 0); - ib_pck_size_i : in std_logic_vector(c_swc_max_pck_size_width - 1 downto 0); - ib_transfer_ack_o : out std_logic; - ib_busy_o : out std_logic - - ); - end component; - - - component swc_pck_transfer_output is - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - - ob_transfer_data_valid_o : out std_logic; - ob_pageaddr_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0); - ob_prio_o : out std_logic_vector(c_swc_prio_width - 1 downto 0); - ob_pck_size_o : out std_logic_vector(c_swc_max_pck_size_width - 1 downto 0); - ob_transfer_data_ack_i : in std_logic; - - pti_transfer_data_valid_i: in std_logic; - pti_transfer_data_ack_o : out std_logic; - pti_pageaddr_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - pti_prio_i : in std_logic_vector(c_swc_prio_width - 1 downto 0); - pti_pck_size_i : in std_logic_vector(c_swc_max_pck_size_width - 1 downto 0) - - ); - end component; - - component swc_pck_transfer_arbiter is - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - - ob_data_valid_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - ob_ack_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - ob_pageaddr_o : out std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - ob_prio_o : out std_logic_vector(c_swc_num_ports * c_swc_prio_width - 1 downto 0); - ob_pck_size_o : out std_logic_vector(c_swc_num_ports * c_swc_max_pck_size_width - 1 downto 0); - - ib_transfer_pck_i : in std_logic_vector(c_swc_num_ports - 1 downto 0); - ib_transfer_ack_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - ib_busy_o : out std_logic_vector(c_swc_num_ports - 1 downto 0); - ib_pageaddr_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - ib_mask_i : in std_logic_vector(c_swc_num_ports * c_swc_num_ports - 1 downto 0); - ib_prio_i : in std_logic_vector(c_swc_num_ports * c_swc_prio_width - 1 downto 0); - ib_pck_size_i : in std_logic_vector(c_swc_num_ports * c_swc_max_pck_size_width - 1 downto 0) - ); - end component; - - component swc_ob_prio_queue is - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - write_i : in std_logic; - read_i : in std_logic; - not_full_o : out std_logic; - not_empty_o : out std_logic; - wr_en_o : out std_logic; - wr_addr_o : out std_logic_vector(c_swc_output_fifo_addr_width - 1 downto 0); - rd_addr_o : out std_logic_vector(c_swc_output_fifo_addr_width - 1 downto 0) - ); - end component; - - component swc_output_block is - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - pta_transfer_data_valid_i : in std_logic; - pta_pageaddr_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - pta_prio_i : in std_logic_vector(c_swc_prio_width - 1 downto 0); - pta_pck_size_i : in std_logic_vector(c_swc_max_pck_size_width - 1 downto 0); - pta_transfer_data_ack_o : out std_logic; - mpm_pgreq_o : out std_logic; - mpm_pgaddr_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0); - mpm_pckend_i : in std_logic; - mpm_pgend_i : in std_logic; - mpm_drdy_i : in std_logic; - mpm_dreq_o : out std_logic; - mpm_data_i : in std_logic_vector(c_swc_data_width - 1 downto 0); - mpm_ctrl_i : in std_logic_vector(c_swc_ctrl_width - 1 downto 0); - mpm_sync_i : in std_logic; - ppfm_free_o : out std_logic; - ppfm_free_done_i : in std_logic; - ppfm_free_pgaddr_o : out std_logic_vector(c_swc_page_addr_width - 1 downto 0); - rx_sof_p1_o : out std_logic; - rx_eof_p1_o : out std_logic; - rx_dreq_i : in std_logic; - rx_ctrl_o : out std_logic_vector(c_swc_ctrl_width - 1 downto 0); - rx_data_o : out std_logic_vector(c_swc_data_width - 1 downto 0); - rx_valid_o : out std_logic; - rx_bytesel_o : out std_logic; - rx_idle_o : out std_logic; - rx_rerror_p1_o : out std_logic; - rx_terror_p1_i : in std_logic; - rx_tabort_p1_i : in std_logic - ); - end component; - -component swc_multiport_pck_pg_free_module is - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - - ib_force_free_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - ib_force_free_done_o : out std_logic_vector(c_swc_num_ports-1 downto 0); - ib_force_free_pgaddr_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - - ob_free_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - ob_free_done_o : out std_logic_vector(c_swc_num_ports-1 downto 0); - ob_free_pgaddr_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - - ll_read_addr_o : out std_logic_vector(c_swc_num_ports * c_swc_page_addr_width -1 downto 0); - --ll_read_data_i : in std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0); - ll_read_data_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - ll_read_req_o : out std_logic_vector(c_swc_num_ports-1 downto 0); - ll_read_valid_data_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - - mmu_free_o : out std_logic_vector(c_swc_num_ports-1 downto 0); - mmu_free_done_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - mmu_free_pgaddr_o : out std_logic_vector(c_swc_num_ports * c_swc_page_addr_width -1 downto 0); - - mmu_force_free_o : out std_logic_vector(c_swc_num_ports-1 downto 0); - mmu_force_free_done_i : in std_logic_vector(c_swc_num_ports-1 downto 0); - mmu_force_free_pgaddr_o : out std_logic_vector(c_swc_num_ports * c_swc_page_addr_width -1 downto 0) - ); - end component; - - - component swc_pck_pg_free_module is - - port ( - clk_i : in std_logic; - rst_n_i : in std_logic; - - ib_force_free_i : in std_logic; - ib_force_free_done_o : out std_logic; - ib_force_free_pgaddr_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - - ob_free_i : in std_logic; - ob_free_done_o : out std_logic; - ob_free_pgaddr_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - - ll_read_addr_o : out std_logic_vector(c_swc_page_addr_width -1 downto 0); - ll_read_data_i : in std_logic_vector(c_swc_page_addr_width - 1 downto 0); - ll_read_req_o : out std_logic; - ll_read_valid_data_i : in std_logic; - - mmu_free_o : out std_logic; - mmu_free_done_i : in std_logic; - mmu_free_pgaddr_o : out std_logic_vector(c_swc_page_addr_width -1 downto 0); - - mmu_force_free_o : out std_logic; - mmu_force_free_done_i : in std_logic; - mmu_force_free_pgaddr_o : out std_logic_vector(c_swc_page_addr_width -1 downto 0) - - - ); - end component; - -end swc_swcore_pkg; - - - - - - -package body swc_swcore_pkg is - - - - -end swc_swcore_pkg; -- GitLab