------------------------------------------------------------------------------- -- Title : ni_resync -- Project : Network Interface (NI) for the ALICE TRD TRAP3 ------------------------------------------------------------------------------- -- File : ni_resync.vhd -- Author : Rolf Schneider -- Company : University Heidelberg - KIP -- Last update: 2003-12-11 -- Platform : Synopsys - v2003.03 ------------------------------------------------------------------------------- -- Description: resynchronization unit from DDR input to sync. output ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2003/03/06 1.0 schneide Created -- 2003/12/11 1.1 schneide Names for rising/falling fetch regs -- 2004/03/24 1.1 schneide Reset&Clear for all registers and reg. -- clear for U_grayc_rising added ------------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; ---------------------------------------------------------------------------------------------------- -- ENTITY ---------------------------------------------------------------------------------------------------- entity ni_resync is generic( width : integer := 10; -- width of the external interface with_out_reg : integer := 1); port( clk : in std_logic; -- internal clock clear_n : in std_logic; -- clear strobe : in std_logic; -- incoming DDR strobe signal data_in : in std_logic_vector(width-1 downto 0); -- incoming DDR data sync. to strobe valid : out std_logic; -- outgoing data valid signal data_out : out std_logic_vector((2*width)-1 downto 0)); -- data output, sync. to internal clk end ni_resync; ---------------------------------------------------------------------------------------------------- -- ARCHITECTURE ---------------------------------------------------------------------------------------------------- architecture v of ni_resync is -- CONSTANTS ------------------------------------------------------------------------------------- constant gray0 : std_logic_vector(1 downto 0) := "00"; -- constant gray counter codes ... constant gray1 : std_logic_vector(1 downto 0) := "01"; constant gray2 : std_logic_vector(1 downto 0) := "11"; constant gray3 : std_logic_vector(1 downto 0) := "10"; -- SIGNALS --------------------------------------------------------------------------------------- signal data0pos, data1pos, data2pos, data3pos : std_logic_vector(width-1 downto 0); signal data0neg, data1neg, data2neg, data3neg : std_logic_vector(width-1 downto 0); signal gray_cnt, old_cnt, nxt_cnt, new_cnt : std_logic_vector(1 downto 0); signal gray_cntf : std_logic_vector(1 downto 0); signal data_o_i : std_logic_vector(data_out'range); signal valid_i : std_logic; signal clear_n_i : std_logic; -- STRUCTURE ------------------------------------------------------------------------------------- begin -- generate a glitch-free clear signal to async. reset gray counter U_clear: process(clk) begin if rising_edge(clk) then clear_n_i <= clear_n; end if; end process; -- fetch data on rising edge of strobe signal into one of four registers -- depending on the gray counter 'gray_cnt' and increment 'gray_cnt' U_grayc_rising: process(strobe, clear_n_i) begin if clear_n_i = '0' then gray_cnt <= gray0; elsif rising_edge(strobe) then case gray_cnt is when gray0 => gray_cnt <= gray1; when gray1 => gray_cnt <= gray2; when gray2 => gray_cnt <= gray3; when gray3 => gray_cnt <= gray0; -- be more pesimistic in functional simulation... when others => gray_cnt <= (others => '-'); end case; end if; end process; U_gray_falling: process(strobe, clear_n_i) begin if clear_n_i = '0' then gray_cntf <= gray0; elsif falling_edge(strobe) then case gray_cntf is when gray0 => gray_cntf <= gray1; when gray1 => gray_cntf <= gray2; when gray2 => gray_cntf <= gray3; when gray3 => gray_cntf <= gray0; -- be more pesimistic in functional simulation... when others => gray_cntf <= (others => '-'); end case; end if; end process; U_fetch_rising: process(strobe) begin if rising_edge(strobe) then case gray_cnt is when gray0 => data0pos <= data_in; when gray1 => data1pos <= data_in; when gray2 => data2pos <= data_in; when gray3 => data3pos <= data_in; -- be more pesimistic in functional simulation... when others => data0pos <= (others => '-'); data1pos <= (others => '-'); data2pos <= (others => '-'); data3pos <= (others => '-'); end case; end if; end process; -- fetch data on falling edge of strobe signal into one of four registers -- depending on the gray counter 'gray_cntf U_fetch_falling: process(strobe) begin if falling_edge(strobe) then case gray_cntf is when gray0 => data0neg <= data_in; when gray1 => data1neg <= data_in; when gray2 => data2neg <= data_in; when gray3 => data3neg <= data_in; -- be more pesimistic in functional simulation... when others => data0neg <= (others => '-'); data1neg <= (others => '-'); data2neg <= (others => '-'); data3neg <= (others => '-'); end case; end if; end process; -- prepare next value of old_cnt with old_cnt select nxt_cnt <= gray1 when gray0, gray2 when gray1, gray3 when gray2, gray0 when gray3, -- be more pesimistic in functional simulation... (others => '-') when others; -- data is valid if new_cnt and old_cnt differs for more than one clock cycle valid_i <= '1' when new_cnt /= old_cnt else '0'; -- synchronize to the system clock U_old_cnt: process(clk, clear_n_i) begin if clear_n_i = '0' then new_cnt <= (others => '0'); old_cnt <= (others => '0'); elsif rising_edge(clk) then new_cnt <= gray_cntf; if valid_i = '1' then old_cnt <= nxt_cnt; end if; end if; end process; -- select the valid output register with old_cnt select data_o_i <= data0pos & data0neg when gray0, data1pos & data1neg when gray1, data2pos & data2neg when gray2, data3pos & data3neg when gray3, -- be more pesimistic in functional simulation... (others => '-') when others; -- the we_n signal for the fifos correspond to the valid signal org: if with_out_reg = 1 generate process(clk) begin if clk'event and clk='1' then valid <= valid_i; data_out <= data_o_i; end if; end process; end generate; do: if with_out_reg = 0 generate valid <= valid_i; data_out <= data_o_i; end generate; end;