--======================================================================================= -- TITLE : Interface synchronization on the 50MHz clock -- DESCRIPTION : Manage interface between 250MHz clock domain and 50MHz clock domain -- FILE : interface_sync_50MHz.vhd -- COMPANY : Micro-Cameras & Space Exploration SA --======================================================================================= -- CREATION -- DATE AUTHOR PROJECT REVISION -- 25/03/2011 JGi 110325a --======================================================================================= -- MODIFICATION HISTORY -- DATE AUTHOR PROJECT REVISION COMMENTS -- 25/03/2011 JGi 110325a Description --======================================================================================= -- Library Definition library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- Entity Definition entity interface_sync_50MHz is port( --clock clk_50MHz : in std_logic; clk_250MHz : in std_logic; --250MHz inputs config_done : in std_logic; trigger_active : in std_logic; trigger_ID_done : in std_logic; trigger_ID : in std_logic_vector(55 downto 0); --50MHz inputs trigger_ID_read : in std_logic; trigger_cnt_read : in std_logic; --outputs sync_config_done : out std_logic; sync_trigger_active : out std_logic; sync_trigger_ID_ready : out std_logic; sync_trigger_ID : out std_logic_vector(55 downto 0); trigger_cnt_valid : out std_logic; trigger_cnt_copy : out std_logic_vector(31 downto 0)); end interface_sync_50MHz; -- Architecture Definition architecture RTL of interface_sync_50MHz is type t_reg_50 is record -- Ouput register declaration sync_config_done : std_logic_vector(3 downto 0); sync_trigger_active : std_logic_vector(3 downto 0); sync_trigger_ID_ready : std_logic_vector(3 downto 0); sync_trigger_ID : std_logic_vector(111 downto 0); trigger_cnt_valid : std_logic; trigger_cnt_copy : std_logic_vector(31 downto 0); end record; type t_reg_250 is record -- Internal register declaration config_done : std_logic; sync_config_done : std_logic_vector(1 downto 0); trigger_active : std_logic; sync_trigger_active : std_logic_vector(1 downto 0); trigger_ID_done : std_logic; sync_trigger_ID_done : std_logic_vector(1 downto 0); end record; signal i_next_reg_250 : t_reg_250 := (config_done => '0', sync_config_done => (others => '0'), trigger_active => '0', sync_trigger_active => (others => '0'), trigger_ID_done => '0', sync_trigger_ID_done => (others => '0')); signal i_reg_250 : t_reg_250 := (config_done => '0', sync_config_done => (others => '0'), trigger_active => '0', sync_trigger_active => (others => '0'), trigger_ID_done => '0', sync_trigger_ID_done => (others => '0')); signal i_next_reg_50 : t_reg_50 := (sync_config_done => (others => '0'), sync_trigger_active => (others => '0'), sync_trigger_ID_ready => (others => '0'), sync_trigger_ID => (others => '0'), trigger_cnt_valid => '0', trigger_cnt_copy => (others => '0')); signal i_reg_50 : t_reg_50 := (sync_config_done => (others => '0'), sync_trigger_active => (others => '0'), sync_trigger_ID_ready => (others => '0'), sync_trigger_ID => (others => '0'), trigger_cnt_valid => '0', trigger_cnt_copy => (others => '0')); begin -- Combinatorial logic -- Manage signals on the 250MHz side process(config_done, trigger_active, trigger_ID_done, i_reg_50, i_reg_250) variable v_reg : t_reg_250 := (config_done => '0', sync_config_done => (others => '0'), trigger_active => '0', sync_trigger_active => (others => '0'), trigger_ID_done => '0', sync_trigger_ID_done => (others => '0')); begin v_reg := i_reg_250; --=================================================================================== --=================================================================================== -- Generate signals until they have been received by the 50MHz interface --=================================================================================== -- Synchronized config done from 50MHz interface v_reg.sync_config_done(0) := i_reg_50.sync_config_done(1); v_reg.sync_config_done(1) := i_reg_250.sync_config_done(0); -- Set config done high when detected at input if config_done = '1' then v_reg.config_done := '1'; -- Reset config done when set high by the 50MHz part elsif i_reg_250.sync_config_done(1) = '1' then v_reg.config_done := '0'; end if; -- Synchronized trigger active from 50MHz interface v_reg.sync_trigger_active(0) := i_reg_50.sync_trigger_active(1); v_reg.sync_trigger_active(1) := i_reg_250.sync_trigger_active(0); -- Set trigger active high when detected at input if trigger_active = '1' then v_reg.trigger_active := '1'; -- Reset trigger active when set high by the 50MHz part elsif i_reg_250.sync_trigger_active(1) = '1' then v_reg.trigger_active := '0'; end if; -- Detect rising edge on trigger ID ready from 50MHz interface if i_reg_50.sync_trigger_ID_ready(1) = '1' and i_reg_50.sync_trigger_ID_ready(2) = '0' then v_reg.sync_trigger_ID_done(0) := '1'; else v_reg.sync_trigger_ID_done(0) := '0'; end if; v_reg.sync_trigger_ID_done(1) := i_reg_250.sync_trigger_ID_done(0); -- Set trigger ID done high when detected at input if trigger_ID_done = '1' then v_reg.trigger_ID_done := '1'; -- Reset trigger ID done when set high by the 50MHz part elsif i_reg_250.sync_trigger_ID_done(1) = '1' then v_reg.trigger_ID_done := '0'; end if; --=================================================================================== --=================================================================================== -- Drive register input i_next_reg_250 <= v_reg; --=================================================================================== end process; -- Manage signals on the 50MHz side process(trigger_ID_read, trigger_ID, trigger_cnt_read, i_reg_250, i_reg_50) variable v_reg : t_reg_50 := (sync_config_done => (others => '0'), sync_trigger_active => (others => '0'), sync_trigger_ID_ready => (others => '0'), sync_trigger_ID => (others => '0'), trigger_cnt_valid => '0', trigger_cnt_copy => (others => '0')); begin v_reg := i_reg_50; --=================================================================================== --=================================================================================== -- Synchronize signals from the 250MHz side --=================================================================================== -- Synchronize config done from the 250MHz interface v_reg.sync_config_done(0) := i_reg_250.config_done; v_reg.sync_config_done(1) := i_reg_50.sync_config_done(0); v_reg.sync_config_done(2) := i_reg_50.sync_config_done(1); -- Set config done on 50MHz when set by 250MHz interface if i_reg_50.sync_config_done(1) = '1' and i_reg_50.sync_config_done(2) = '0' and i_reg_50.sync_config_done(3) = '0' then v_reg.sync_config_done(3) := '1'; else v_reg.sync_config_done(3) := '0'; end if; -- Synchronize trigger active from the 250MHz interface v_reg.sync_trigger_active(0) := i_reg_250.trigger_active; v_reg.sync_trigger_active(1) := i_reg_50.sync_trigger_active(0); -- Synchronize trigger ID ready from the 250MHz interface v_reg.sync_trigger_ID_ready(0) := i_reg_250.trigger_ID_done; v_reg.sync_trigger_ID_ready(1) := i_reg_50.sync_trigger_ID_ready(0); v_reg.sync_trigger_ID_ready(2) := i_reg_50.sync_trigger_ID_ready(1); -- Set trigger ready when set on the 250MHz side and release it -- when read by the 50MHz side if trigger_ID_read = '1' then v_reg.sync_trigger_ID_ready(3) := '0'; elsif i_reg_50.sync_trigger_ID_ready(1) = '1' and i_reg_50.sync_trigger_ID_ready(2) = '0' then v_reg.sync_trigger_ID_ready(3) := '1'; end if; -- Simply synchronize trigger ID v_reg.sync_trigger_ID(55 downto 0) := trigger_ID; v_reg.sync_trigger_ID(111 downto 56) := i_reg_50.sync_trigger_ID(55 downto 0); -- Counter is a simple copy of the counter of the synchronized trigger ID v_reg.trigger_cnt_valid := trigger_cnt_read; if trigger_cnt_read = '1' then v_reg.trigger_cnt_copy := i_reg_50.sync_trigger_ID(87 downto 56); end if; --=================================================================================== --=================================================================================== -- Drive register input i_next_reg_50 <= v_reg; --=================================================================================== -- Output assignation sync_config_done <= i_reg_50.sync_config_done(3); sync_trigger_active <= i_reg_50.sync_trigger_active(1); sync_trigger_ID_ready <= i_reg_50.sync_trigger_ID_ready(3); sync_trigger_ID <= i_reg_50.sync_trigger_ID(111 downto 56); trigger_cnt_valid <= i_reg_50.trigger_cnt_valid; trigger_cnt_copy <= i_reg_50.trigger_cnt_copy; --=================================================================================== end process; -- Sequential logic process(clk_250MHz) begin if rising_edge(clk_250MHz) then i_reg_250 <= i_next_reg_250; end if; end process; process(clk_50MHz) begin if rising_edge(clk_50MHz) then i_reg_50 <= i_next_reg_50; end if; end process; end RTL;