-- -- Synchro LocalLink MUX Controller -- -- Original author Barry Green -- re-worked (not nessesarily for the better) by Matt Warren. -- -- At some point we should start thinking about timeouts when waiting for EOFs -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity ll_syncmux_ctrl is generic( NLEVELS : integer := 4 -- number of levels of data, not muxs ); port( src_rdy_i : in std_logic_vector (2**NLEVELS-1 downto 0); eof_i : in std_logic_vector (2**NLEVELS-1 downto 0); dst_rdy_o : out std_logic_vector (2**NLEVELS-1 downto 0); dst_rdy_i : in std_logic; freeze_o : out std_logic; sel_o : out std_logic_vector (NLEVELS-1 downto 0); rst : in std_logic; clk : in std_logic ); -- Declarations end ll_syncmux_ctrl; -- architecture rtl of ll_syncmux_ctrl is constant NPORTS : integer := (2**NLEVELS); type states is( Idle, StartChannel, WaitEOF, EndChannel ); signal state, nstate : states; signal selected_channel : integer range (NPORTS-1) downto 0; signal offset_channel : integer range (NPORTS-1) downto 0; signal channel_inc : std_logic; signal local_dst_rdy : std_logic_vector (2**NLEVELS-1 downto 0); begin freeze_o <= not(dst_rdy_i); -- Assert dst_rdy until we see a src_rdy on each channel, then hand control -- to the mux controller. -- This shouldn't be needed if the source works correctly. -- fluffer_gen : for f in 0 to 15 generate -- prc_fluffer : process (selected_channel, src_rdy_i, local_dst_rdy ) -- begin -- if ((selected_channel /= f) and (src_rdy_i(f) = '0')) then -- dst_rdy_o(f) <= '1'; -- else -- dst_rdy_o(f) <= local_dst_rdy(f); -- end if; -- end process; -- end generate; dst_rdy_o <= local_dst_rdy; -- SM Clocked ------------------------------------------------------- prc_sm_clocked : process(clk) begin if rising_edge(clk) then if (rst = '1') then state <= Idle; else state <= nstate; end if; end if; end process; -- SM Async ------------------------------------------------------- prc_sm_async : process(state, src_rdy_i, eof_i, dst_rdy_i, selected_channel) begin channel_inc <= '0'; local_dst_rdy <= (others => '0'); case state is when Idle => channel_inc <= '1'; if (src_rdy_i(selected_channel) = '1') then channel_inc <= '0'; nstate <= WaitEOF; --StartChannel; else nstate <= Idle; end if; when StartChannel => -- imposes 1 clock delay --local_dst_rdy(selected_channel) <= dst_rdy_i; nstate <= WaitEOF; when WaitEOF => local_dst_rdy(selected_channel) <= dst_rdy_i; if (eof_i(selected_channel) = '1') then nstate <= EndChannel; else nstate <= WaitEOF; end if; when EndChannel => local_dst_rdy(selected_channel) <= dst_rdy_i; nstate <= Idle; when others => nstate <= Idle; end case; end process; -- Port select counter -- The ordering could be more complicated with priority ports etc -- selected_channel <= 0; -- offset_channel <= 0; prc_port_sel_counter : process(clk) begin if rising_edge(clk) then if (rst = '1') then selected_channel <= 0; offset_channel <= 2; else if (channel_inc = '1') then if (selected_channel < (NPORTS-1)) then --if (selected_channel < 3) then selected_channel <= selected_channel + 1; else selected_channel <= 0; end if; if (offset_channel < (NPORTS-1)) then --if (offset_channel < 3) then offset_channel <= offset_channel + 1; else offset_channel <= 0; end if; end if; end if; end if; end process; Sel_O <= conv_std_logic_vector(selected_channel, NLEVELS); end architecture rtl;