]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
link synchronizer for Mupix 8.
authorTobias Weber <toweber86@gmail.com>
Thu, 31 May 2018 10:40:50 +0000 (12:40 +0200)
committerTobias Weber <toweber86@gmail.com>
Thu, 31 May 2018 10:40:50 +0000 (12:40 +0200)
mupix/Mupix8/sources/LinkSynchronizer.vhd [new file with mode: 0644]
mupix/Mupix8/tb/LinkSynchronizerTest.vhd [new file with mode: 0644]

diff --git a/mupix/Mupix8/sources/LinkSynchronizer.vhd b/mupix/Mupix8/sources/LinkSynchronizer.vhd
new file mode 100644 (file)
index 0000000..c90aff6
--- /dev/null
@@ -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 (file)
index 0000000..fbf79a9
--- /dev/null
@@ -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;