diff --git a/hdl/eb_slave_core/eb_fifo.vhd b/hdl/eb_slave_core/eb_fifo.vhd new file mode 100644 index 0000000000000000000000000000000000000000..72bd261f36be4912c7afa76155eb1cf88ac4c1af --- /dev/null +++ b/hdl/eb_slave_core/eb_fifo.vhd @@ -0,0 +1,102 @@ +------------------------------------------------------------------------------ +-- Title : Etherbone FIFO +-- Project : Etherbone Core +------------------------------------------------------------------------------ +-- File : eb_fifo.vhd +-- Author : Wesley W. Terpstra +-- Company : GSI +-- Created : 2013-04-08 +-- Last update: 2013-04-08 +-- Platform : FPGA-generic +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: A convenience wrapper for FIFOs used in Etherbone +------------------------------------------------------------------------------- +-- Copyright (c) 2013 GSI +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2013-04-08 1.0 terpstra Created +------------------------------------------------------------------------------- + +-- r_dat_o is valid when r_empty_o=0 +-- w_dat_i is valid when w_push_i =1 +-- r_pop_i affects r_empty_o on the next cycle +-- w_push_i affects w_full_o on the next cycle +entity eb_fifo is + generic( + g_width : natural; + g_size : natural); + port( + clk_i : in std_logic; + rstn_i : in std_logic; + w_full_o : out std_logic; + w_push_i : in std_logic; + w_dat_i : in std_logic_vector(g_width-1 downto 0); + r_empty_o : out std_logic; + r_pop_i : in std_logic; + r_dat_o : out std_logic_vector(g_width-1 downto 0)); +end eb_fifo; + +architecture rtl of eb_fifo is + constant c_depth : natural := f_ceil_log2(g_size); + + signal r_idx : unsigned(c_depth downto 0); + signal w_idx : unsigned(c_depth downto 0); + signal r_idx1 : unsigned(c_depth downto 0); + signal w_idx1 : unsigned(c_depth downto 0); + + constant c_high : unsigned(c_depth downto 0) := (c_depth => '1', others => '0'); + +begin + + ram : generic_simple_dpram + generic map( + g_data_width => g_width, + g_size => g_size, + g_dual_clock => false) + port map( + rst_n_i => rstn_i, + + clka_i => clk_i, + bwea_i => (others => '1'), + wea_i => w_push_i, + aa_i => w_idx(c_depth-1 downto 0), + da_i => w_dat_i, + + clkb_i => clk_i, + ab_i => r_idx(c_depth-1 downto 0), + qb_o => r_dat_o); + + r_idx1 <= (r_idx+1) when r_pop_i ='1' else r_idx; + w_idx1 <= (w_idx+1) when r_push_i='1' else w_idx; + + main : process(rstn_i, clk_i) is + begin + if rstn_i = '0' then + r_idx <= (others => '0'); + w_idx <= (others => '0'); + w_full_o <= '0'; + r_empty_o <= '1'; + elsif rising_edge(clk_i) then + r_idx <= r_idx1; + w_idx <= w_idx1; + + -- Compare the newest pointers + if (w_idx1 xor c_high) = r_idx1 then + full_o <= '1'; + else + full_o <= '0'; + end if; + + -- Use the OLD write pointer to prevent read-during-write + if w_idx = r_idx1 then + empty_o <= '1'; + else + empty_o <= '0'; + end if; + + end if; + end process; + +end rtl; diff --git a/hdl/eb_slave_core/eb_internals_pkg.vhd b/hdl/eb_slave_core/eb_internals_pkg.vhd index b0e4b1413bd7287ea3d55f134f4285660defd8a0..028cd09fb02703d585ddb7567393b9795981e62c 100644 --- a/hdl/eb_slave_core/eb_internals_pkg.vhd +++ b/hdl/eb_slave_core/eb_internals_pkg.vhd @@ -45,4 +45,45 @@ component eb_rx_fsm is wb_stall_i : in std_logic ); end component; +component eb_fifo is + generic( + g_width : natural; + g_size : natural); + port( + clk_i : in std_logic; + rstn_i : in std_logic; + w_full_o : out std_logic; + w_push_i : in std_logic; + w_dat_i : in std_logic_vector(g_width-1 downto 0); + r_empty_o : out std_logic; + r_pop_i : in std_logic; + r_dat_o : out std_logic_vector(g_width-1 downto 0)); +end component; + +component eb_tx_mux is + port( + clk_i : in std_logic; + rstn_i : in std_logic; + + tag_pop_o : out std_logic; + tag_dat_i : in t_tag; + tag_ready_i : in std_logic; + + pass_pop_o : out std_logic; + pass_dat_o : out std_logic_vector(31 downto 0); + pass_ready_i : in std_logic; + + cfg_pop_o : out std_logic; + cfg_dat_i : in std_logic_vector(31 downto 0); + cfg_ready_i : in std_logic; + + wb_pop_o : out t_wishbone_master_out; + wb_dat_i : in std_logic_vector(31 downto 0); + wb_ready_i : in std_logic; + + tx_stb_o : out std_logic; + tx_dat_o : out std_logic_vector(31 downto 0); + tx_stall_i : in std_logic); +end component; + end package; diff --git a/hdl/eb_slave_core/eb_pass_fifo.vhd b/hdl/eb_slave_core/eb_pass_fifo.vhd new file mode 100644 index 0000000000000000000000000000000000000000..c304df9ba101d5392af270c92c4cf203ec836464 --- /dev/null +++ b/hdl/eb_slave_core/eb_pass_fifo.vhd @@ -0,0 +1,62 @@ +------------------------------------------------------------------------------ +-- Title : Etherbone Pass FIFO +-- Project : Etherbone Core +------------------------------------------------------------------------------ +-- File : eb_pass_fifo.vhd +-- Author : Wesley W. Terpstra +-- Company : GSI +-- Created : 2013-04-08 +-- Last update: 2013-04-08 +-- Platform : FPGA-generic +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: Records protocol data that should be put into response +------------------------------------------------------------------------------- +-- Copyright (c) 2013 GSI +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2013-04-08 1.0 terpstra Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wishbone_pkg.all; +use work.eb_internals_pkg.all; + +-- Updates (registered) outputs based on {stb,pop}_i +entity eb_pass_fifo is + port( + clk_i : in std_logic; + rstn_i : in std_logic; + + fsm_stb_i : in std_logic; + fsm_dat_i : in std_logic_vector(31 downto 0); + fsm_full_o : out std_logic; + + mux_pop_i : in std_logic; + mux_dat_o : out std_logic_vector(31 downto 0); + mux_empty_o : out std_logic); +end eb_pass_fifo; + +architecture rtl of eb_pass_fifo is +begin + + fifo : eb_fifo + generic map( + g_data_width => 32, + g_size => 1024) -- 4* the length of the other FIFOs + port map( + clk_i => clk_i, + rs_n_i => rstn_i, + w_full_o => fsm_full_o, + w_push_i => fsm_stb_i, + w_dat_i => fsm_dat_i, + r_empty_o => mux_empty_o, + r_pop_i => mux_pop_i, + r_dat_o => mux_dat_o); + +end rtl; diff --git a/hdl/eb_slave_core/eb_tag_fifo.vhd b/hdl/eb_slave_core/eb_tag_fifo.vhd new file mode 100644 index 0000000000000000000000000000000000000000..d3613b801742c4745837502cad06ff95c4e74583 --- /dev/null +++ b/hdl/eb_slave_core/eb_tag_fifo.vhd @@ -0,0 +1,62 @@ +------------------------------------------------------------------------------ +-- Title : Etherbone Tag FIFO +-- Project : Etherbone Core +------------------------------------------------------------------------------ +-- File : eb_tag_fifo.vhd +-- Author : Wesley W. Terpstra +-- Company : GSI +-- Created : 2013-04-08 +-- Last update: 2013-04-08 +-- Platform : FPGA-generic +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: Tracks which channel the MUX should pop next +------------------------------------------------------------------------------- +-- Copyright (c) 2013 GSI +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2013-04-08 1.0 terpstra Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wishbone_pkg.all; +use work.eb_internals_pkg.all; + +-- Updates (registered) outputs based on {stb,pop}_i +entity eb_tag_fifo is + port( + clk_i : in std_logic; + rstn_i : in std_logic; + + fsm_stb_i : in std_logic; + fsm_dat_i : in t_tag; + fsm_full_o : out std_logic; + + mux_pop_i : in std_logic; + mux_dat_o : out t_tag; + mux_empty_o : out std_logic); +end eb_tag_fifo; + +architecture rtl of eb_tag_fifo is +begin + + fifo : eb_fifo + generic map( + g_data_width => 2, + g_size => 1024) -- 4* the length of the other FIFOs + port map( + clk_i => clk_i, + rs_n_i => rstn_i, + w_full_o => fsm_full_o, + w_push_i => fsm_stb_i, + w_dat_i => fsm_dat_i, + r_empty_o => mux_empty_o, + r_pop_i => mux_pop_i, + r_dat_o => mux_dat_o); + +end rtl; diff --git a/hdl/eb_slave_core/eb_tx_mux.vhd b/hdl/eb_slave_core/eb_tx_mux.vhd new file mode 100644 index 0000000000000000000000000000000000000000..34b91f903116a249b3d2926462fbbb814f42887d --- /dev/null +++ b/hdl/eb_slave_core/eb_tx_mux.vhd @@ -0,0 +1,119 @@ +------------------------------------------------------------------------------ +-- Title : Etherbone TX MUX +-- Project : Etherbone Core +------------------------------------------------------------------------------ +-- File : eb_tux_mux.vhd +-- Author : Wesley W. Terpstra +-- Company : GSI +-- Created : 2013-04-08 +-- Last update: 2013-04-08 +-- Platform : FPGA-generic +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: Combines output streams into a packet +------------------------------------------------------------------------------- +-- Copyright (c) 2013 GSI +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2013-04-08 1.0 terpstra Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wishbone_pkg.all; +use work.eb_internals_pkg.all; + +entity eb_tx_mux is + port( + clk_i : in std_logic; + rstn_i : in std_logic; + + tag_pop_o : out std_logic; + tag_dat_i : in t_tag; + tag_ready_i : in std_logic; + + pass_pop_o : out std_logic; + pass_dat_o : out std_logic_vector(31 downto 0); + pass_ready_i : in std_logic; + + cfg_pop_o : out std_logic; + cfg_dat_i : in std_logic_vector(31 downto 0); + cfg_ready_i : in std_logic; + + wb_pop_o : out t_wishbone_master_out; + wb_dat_i : in std_logic_vector(31 downto 0); + wb_ready_i : in std_logic; + + tx_stb_o : out std_logic; + tx_dat_o : out std_logic_vector(31 downto 0); + tx_stall_i : in std_logic); +end eb_tx_mux; + +architecture rtl of eb_tx_mux is + + signal r_tx_stb : std_logic; + signal s_can_tx : std_logic; + signal s_dat_ready : std_logic; + signal s_dat_value : std_logic_vector(31 downto 0); + signal s_tag_pop : std_logic; + signal r_tag_valid : std_logic; + signal r_tag_value : t_tag; + +begin + + -- We can write whenever TX is unstalled and/or not full + s_can_tx <= not r_tx_stb or not tx_stall_i; + + tx_stb_o <= r_tx_stb; + tx_out : process(clk_i) is + begin + if rstn_i = '0' then + r_tx_stb <= '0'; + tx_dat_o <= '0'; + elsif rising_edge(clk_i) then + -- Can we push the data? + if s_can_tx then + r_tx_stb <= s_dat_ready and r_tag_valid; + tx_dat_o <= s_dat_value; + end if; + end if; + end process; + + -- Pop the queue we fed into TX + pass_pop_o <= s_can_tx and r_tag_valid and pass_ready_i and (r_tag_value = c_tag_pass_on); + cfg_pop_o <= s_can_tx and r_tag_valid and cfg_ready_i and (r_tag_value = c_tag_cfg_req); + wb_pop_o <= s_can_tx and r_tag_valid and wb_ready_i and (r_tag_value = c_tag_wb_drop or r_tag_value = c_tag_wb_copy); + s_tag_pop <= s_can_tx and r_tag_valid and s_dat_ready; + + with r_tag_value select + s_dat_ready <= + cfg_ready_i when c_tag_cfg_req, + pass_ready_i when c_tag_pass_on, + wb_ready_i when others; + + with r_tag_value select + s_dat_value <= + cfg_dat_i when c_tag_cfg_req, + pass_dat_i when c_tag_pass_on, + wb_dat_i when others; + + -- Pop the tag FIFO if the register is empty/emptied + tag_pop_o <= tag_ready_i and (s_tag_pop or not r_tag_valid); + tag_in : process(clk_i) is + begin + if rstn_i = '0' then + r_tag_valid <= '0'; + r_tag_value <= c_tag_wb_drop; + elsif rising_edge(clk_i) then + if s_tag_pop = '1' then + r_tag_valid <= tag_ready_i; + r_tag_value <= tag_dat_i; + end if; + end if; + end process; + +end rtl;