From: Tobias Weber Date: Thu, 31 May 2018 10:40:50 +0000 (+0200) Subject: link synchronizer for Mupix 8. X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=31e0f6f68d64bcb046af8c14e5ba75e01af7aece;p=trb3.git link synchronizer for Mupix 8. --- diff --git a/mupix/Mupix8/sources/LinkSynchronizer.vhd b/mupix/Mupix8/sources/LinkSynchronizer.vhd new file mode 100644 index 0000000..c90aff6 --- /dev/null +++ b/mupix/Mupix8/sources/LinkSynchronizer.vhd @@ -0,0 +1,115 @@ +------------------------------------------------------------------------ +-- Link Synchronizer for TRBv3 Serdes Links +-- From Mupix 8 documentation it is not possible to use the synchronizer +-- present in the Serdes blocks (??). +-- T. Weber, Ruhr University Bochum +------------------------------------------------------------------------ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity LinkSynchronizer is + generic ( + clk_speed : integer := 8); -- clk speed in ns + port ( + clk_in : in std_logic; -- clk in synchronous to serdes rx clock + reset_in : in std_logic; -- reset + comma_in : in std_logic; -- comma word detected by serdes + cverr_in : in std_logic; -- serdes data error in + link_sync_out : out std_logic; -- realign to link out pulse low to high to start word alignminment + link_sync_flag : out std_logic; -- link is synchronous + comma_counter_out : out std_logic_vector(15 downto 0)); -- comma word counter +end entity LinkSynchronizer; + +architecture rtl of LinkSynchronizer is + + constant look_for_comma_period : integer := 1000000; -- period to look for valid commas in ns + constant look_counter_max : integer := look_for_comma_period/clk_speed; + + type sync_state_type is (idle, sync, notsync); + signal sync_fsm : sync_state_type := idle; + + signal look_counter : integer range 0 to look_counter_max - 1 := 0; + signal comma_counter : integer range 0 to 2**16 - 1 := 0; + signal look_enable : std_logic := '0'; + signal comma_seen : std_logic := '0'; + signal link_sync_i : std_logic := '0'; + +begin -- architecture rtl + + counter_proc : process (clk_in) is + begin -- process counter_proc + if rising_edge(clk_in) then + if reset_in = '1' then + look_counter <= 0; + look_enable <= '0'; + else + look_counter <= look_counter + 1; + look_enable <= '0'; + if look_counter = look_counter_max - 1 then + look_enable <= '1'; + look_counter <= 0; + end if; + end if; + end if; + end process counter_proc; + + sync_proc : process (clk_in) is + begin -- process sync_proc + if rising_edge(clk_in) then + if reset_in = '1' then + comma_seen <= '0'; + link_sync_i <= '0'; + comma_counter <= 0; + sync_fsm <= idle; + else + link_sync_i <= '1'; + -- look for incoming comma characters + if comma_in = '1' and cverr_in = '0' then + comma_seen <= '1'; + comma_counter <= comma_counter + 1; + end if; + link_sync_i <= '1'; + case sync_fsm is + when idle => + sync_fsm <= idle; + link_sync_flag <= '0'; + if look_enable = '1' then + if comma_seen = '1' then + sync_fsm <= sync; + else + sync_fsm <= notsync; + link_sync_i <= '0'; + end if; + comma_seen <= '0'; + end if; + when sync => + link_sync_flag <= '1'; + sync_fsm <= sync; + if look_enable = '1' then + if comma_seen = '0' then + sync_fsm <= notsync; + link_sync_i <= '0'; + end if; + comma_seen <= '0'; + end if; + when notsync => + link_sync_flag <= '0'; + sync_fsm <= notsync; + if look_enable = '1' then + if comma_seen = '1' then + sync_fsm <= sync; + else + link_sync_i <= '0'; + end if; + comma_seen <= '0'; + end if; + end case; + end if; + end if; + end process sync_proc; + + comma_counter_out <= std_logic_vector(to_unsigned(comma_counter, 16)); + link_sync_out <= link_sync_i; + +end architecture rtl; diff --git a/mupix/Mupix8/tb/LinkSynchronizerTest.vhd b/mupix/Mupix8/tb/LinkSynchronizerTest.vhd new file mode 100644 index 0000000..fbf79a9 --- /dev/null +++ b/mupix/Mupix8/tb/LinkSynchronizerTest.vhd @@ -0,0 +1,89 @@ +---------------------------------- +--Test bench for link synchronizer +--T. Weber, Ruhr University Bochum +---------------------------------- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity LinkSynchronizerTest is +end entity LinkSynchronizerTest; + +architecture sim of LinkSynchronizerTest is + + component LinkSynchronizer is + generic ( + clk_speed : integer); + port ( + clk_in : in std_logic; + reset_in : in std_logic; + comma_in : in std_logic; + cverr_in : in std_logic; + link_sync_out : out std_logic; + link_sync_flag : out std_logic; + comma_counter_out : out std_logic_vector(15 downto 0)); + end component LinkSynchronizer; + + constant clk_speed : integer := 10; + constant clk_period : time := 10 ns; + + signal clk_in : std_logic; + signal reset_in : std_logic := '0'; + signal comma_in : std_logic := '0'; + signal cverr_in : std_logic := '0'; + signal link_sync_out : std_logic; + signal link_sync_flag : std_logic; + signal comma_counter_out : std_logic_vector(15 downto 0); + + signal generate_commas_i : std_logic := '0'; + signal generate_counter : integer := 0; + +begin + + LinkSynchronizer_1 : entity work.LinkSynchronizer + generic map ( + clk_speed => clk_speed) + port map ( + clk_in => clk_in, + reset_in => reset_in, + comma_in => comma_in, + cverr_in => cverr_in, + link_sync_out => link_sync_out, + link_sync_flag => link_sync_flag, + comma_counter_out => comma_counter_out); + + clk_gen : process is + begin + clk_in <= '0'; + wait for clk_period/2; + clk_in <= '1'; + wait for clk_period/2; + end process clk_gen; + + comma_gen : process(clk_in) is + begin -- process comma_gen + if rising_edge(clk_in) then + comma_in <= '0'; + if generate_commas_i = '1' then + generate_counter <= generate_counter + 1; + if generate_counter = 200 then + generate_counter <= 0; + comma_in <= '1'; + end if; + end if; + end if; + end process comma_gen; + + stimulus : process is + begin + generate_commas_i <= '0'; + wait for 3 ms; + generate_commas_i <= '1'; + wait for 3 ms; + generate_commas_i <= '0'; + wait for 3 ms; + generate_commas_i <= '1'; + wait; + end process stimulus; + +end architecture;