library IEEE; use IEEE.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity resync_sdr is generic( width : integer := 4; -- width of the external interface with_in_reg : boolean := true; -- with input register with_out_reg : boolean := true); -- with output register port( clear_n : in std_logic; -- clear, synchronized inside clk_in : in std_logic; -- incoming clk_in signal valid_in : in std_logic; -- incoming data valid data_in : in std_logic_vector(width-1 downto 0); -- incoming data sync. to clk_in clk_out : in std_logic; -- read clock valid_out : out std_logic; -- outgoing data valid signal data_out : out std_logic_vector(width-1 downto 0)); -- data output, sync. to clk_out end resync_sdr; architecture v of resync_sdr is -- next value of the 2-bit Gray code function gray2next(ain : std_logic_vector(1 downto 0)) return std_logic_vector is begin return ain(0) & not ain(1); end gray2next; subtype data_type is std_logic_vector(data_in'range); type data_block is array(0 to 3) of data_type; signal data_in_i : data_type; signal dreg : data_block; signal gray_cnt, old_cnt, new_cnt : std_logic_vector(1 downto 0); signal data_o_i : data_type; signal valid_in_i : std_logic; signal valid_i : std_logic; signal clear_n_in : std_logic; signal clear_n_out : std_logic; begin -- input register irg1: if with_in_reg generate process(clk_in) begin if rising_edge(clk_in) then valid_in_i <= valid_in; data_in_i <= data_in; end if; end process; end generate; -- no input register irg0: if not with_in_reg generate valid_in_i <= valid_in; data_in_i <= data_in; end generate; -- fetch data_in on rising edge of clk_in into one of four registers -- depending on the Gray counter 'gray_cnt' and increment 'gray_cnt' grayc_in: process(clk_in) begin if rising_edge(clk_in) then clear_n_in <= clear_n; -- synchronize the clear signal if clear_n_in = '0' then gray_cnt <= (others => '0'); elsif valid_in_i = '1' then gray_cnt <= gray2next(gray_cnt); -- Gray counter end if; if valid_in_i = '1' then dreg(conv_integer(gray_cnt)) <= data_in_i; -- write end if; end if; end process; -- data is valid if new_cnt and old_cnt differ valid_i <= '1' when new_cnt /= old_cnt else '0'; -- sync register and output Gray counter to_clk_out: process(clk_out) begin if rising_edge(clk_out) then clear_n_out <= clear_n; -- synchronize to the output clock if clear_n_out = '0' then new_cnt <= (others => '0'); old_cnt <= (others => '0'); else new_cnt <= gray_cnt; -- clock domain crossing if valid_i = '1' then old_cnt <= gray2next(old_cnt); -- Gray counter end if; end if; end if; end process; -- output mux, old_cnt is the read pointer data_o_i <= dreg(conv_integer(old_cnt)); -- registered output org1: if with_out_reg generate process(clk_out) begin if clk_out'event and clk_out='1' then valid_out <= valid_i; data_out <= data_o_i; end if; end process; end generate; -- without output register org0: if not with_out_reg generate valid_out <= valid_i; data_out <= data_o_i; end generate; end;