tdc_psync.vhd 1.98 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
-------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_psync
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Pulse synchronizer
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-14 SB Created file
-------------------------------------------------------------------------------

-- Copyright (C) 2011 Sebastien Bourdeauducq

library ieee;
use ieee.std_logic_1164.all;

23 24 25
library work;
use work.tdc_package.all;

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
entity tdc_psync is
    port(
        clk_src_i : in std_logic;
        p_i       : in std_logic;
        
        clk_dst_i : in std_logic;
        p_o       : out std_logic
    );
end entity;

architecture rtl of tdc_psync is
-- Initialize registers at FPGA configuration.
signal level    : std_logic := '0';
signal level_d1 : std_logic := '0';
signal level_d2 : std_logic := '0';
signal level_d3 : std_logic := '0';
-- Prevent inference of a SRL* primitive, which does not
-- have good metastability resistance.
attribute keep: string;
attribute keep of level_d1: signal is "true";
attribute keep of level_d2: signal is "true";
attribute keep of level_d3: signal is "true";
begin
    -- Convert incoming pulses into level flips.
    process(clk_src_i)
    begin
        if rising_edge(clk_src_i) then
            if p_i = '1' then
                level <= not level;
            end if;
        end if;
    end process;
    
    -- Synchronize level to clk_dst domain and register.
    process(clk_dst_i)
    begin
        if rising_edge(clk_dst_i) then
            level_d1 <= level;
            level_d2 <= level_d1;
            level_d3 <= level_d2;
        end if;
    end process;
    
69
    -- Convert level flips back into pulses synchronous to clk_dst domain.
70 71
    p_o <= level_d2 xor level_d3;
end architecture;