-- -- 4b symbol dedoder -- -- Matt Warren July 2015 -- -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library readout130; use readout130.pkg_star_flink.all; entity star_flink_decoder is port( -- 160 MHz domain ----------------------------------------- ser_i : in std_logic; -- serial input clk160 : in std_logic; -- sample clock -- 40MHz domain ------------------------------------------------ symbol_align_i : in std_logic_vector(2 downto 0); -- alignment control symbol_o : out std_logic_vector(3 downto 0); -- output of deser after alignment output_en_i : in std_logic; -- enable signals after align isidle_o : out std_logic; -- might be useful for auto-align error_o : out std_logic; -- asserted if a symbol decodes as "1111" or "0000" -- Signals/data out bcr_o : out std_logic; ls_o : out std_logic; l0id_o : out std_logic_vector(7 downto 0); -- single L0ID bus pr_valid_o : out std_logic; -- L0ID is for PR lp_valid_o : out std_logic; -- L0ID is for LP -- Infra clk : in std_logic; rst : in std_logic ); -- Declarations end star_flink_decoder; --------------------------------------------------------------------------- architecture rtl of star_flink_decoder is signal ser_in0 : std_logic; signal ser_in1 : std_logic; signal sr0 : std_logic_vector(7 downto 0); signal sr1 : std_logic_vector(7 downto 0); signal symbol : std_logic_vector(3 downto 0); signal symb_count : std_logic_vector(1 downto 0); signal pr_mode : std_logic; signal lp_mode : std_logic; begin -- Toy 160Mb Deserialiser (sim only) --=========================================================== -- This demonstates using DDR as an easy way to control -- sample phase in the slower clock domain ser_in0 <= ser_i when rising_edge(clk160); ser_in1 <= ser_i when falling_edge(clk160); -- Shift in 160Mb data, prc_deser160 : process (clk160) begin if rising_edge(clk160) then if (rst = '1') then sr0 <= (others => '0'); sr1 <= (others => '0'); else sr0 <= sr0(6 downto 0) & ser_in0; sr1 <= sr1(6 downto 0) & ser_in1; end if; end if; end process; -- Alignment of 4b symbols to 40MHz clock (incl. sample phase) --=========================================================== prc_align40 : process (clk) begin if rising_edge(clk) then case symbol_align_i is when "000" => symbol <= sr0(3 downto 0); when "001" => symbol <= sr1(3 downto 0); when "010" => symbol <= sr0(4 downto 1); when "011" => symbol <= sr1(4 downto 1); when "100" => symbol <= sr0(5 downto 2); when "101" => symbol <= sr1(5 downto 2); when "110" => symbol <= sr0(6 downto 3); when "111" => symbol <= sr1(6 downto 3); when others => null; end case; end if; end process; symbol_o <= symbol; -- Main Event: Decode symbols and assemble output signals --========================================================== prc_decode_out : process (clk) variable data_3b : std_logic_vector(2 downto 0); variable symb_count_clr : std_logic; variable symb_count_inc : std_logic; begin if rising_edge(clk) then if (rst = '1') or (output_en_i = '0') then isidle_o <= '0'; bcr_o <= '0'; ls_o <= '0'; pr_mode <= '0'; lp_mode <= '0'; data_3b := "000"; l0id_o <= x"00"; pr_valid_o <= '0'; lp_valid_o <= '0'; symb_count <= "00"; symb_count_clr := '0'; symb_count_inc := '0'; error_o <= '0'; else -- Decode symbols ------------------------------------------------------- -- defaults isidle_o <= '0'; ls_o <= '0'; bcr_o <= '0'; data_3b := "000"; pr_valid_o <= '0'; lp_valid_o <= '0'; symb_count_clr := '0'; symb_count_inc := '0'; error_o <= '0'; case symbol is when sBCR => bcr_o <= '1'; when sLS => ls_o <= '1'; when sBCRLS => bcr_o <= '1'; ls_o <= '1'; when sPR => pr_mode <= '1'; lp_mode <= '0'; symb_count_clr := '1'; when sLP => pr_mode <= '0'; lp_mode <= '1'; symb_count_clr := '1'; when sDATA0 => data_3b := "000"; symb_count_inc := '1'; when sDATA1 => data_3b := "001"; symb_count_inc := '1'; when sDATA2 => data_3b := "010"; symb_count_inc := '1'; when sDATA3 => data_3b := "011"; symb_count_inc := '1'; when sDATA4 => data_3b := "100"; symb_count_inc := '1'; when sDATA5 => data_3b := "101"; symb_count_inc := '1'; when sDATA6 => data_3b := "110"; symb_count_inc := '1'; when sDATA7 => data_3b := "111"; symb_count_inc := '1'; when sIDLE => isidle_o <= '1'; when others => error_o <= '1'; end case; -- Data symbol counter if (symb_count_clr = '1') then symb_count <= "00"; elsif (symb_count_inc = '1') then symb_count <= symb_count + '1'; end if; -- Assemble L0ID and Valid outputs ----------------------------------------------------------- case symb_count is when "00" => l0id_o(7 downto 6) <= data_3b(1 downto 0); when "01" => l0id_o(5 downto 3) <= data_3b; when "10" => l0id_o(2 downto 0) <= data_3b; pr_valid_o <= pr_mode; lp_valid_o <= lp_mode; --when "11" => l0id_o <= x"00"; -- not needed, for debug only when others => null; end case; end if; end if; end process; end rtl;