library ieee;
use ieee.std_logic_1164.all;

entity pfd_sync is
    port (
        clk    : in  std_logic;                     -- fast clock
        rst_n  : in  std_logic;                     -- active-low synchronous reset
        ref_in : in  std_logic;                     -- asynchronous reference
        fb_in  : in  std_logic;                     -- asynchronous feedback
        up     : out std_logic;                     -- ref leads fb
        dn     : out std_logic                      -- fb leads ref
    );
end entity;

architecture rtl of pfd_sync is
    -- 2-stage synchronizers
    signal ref_sync : std_logic_vector(1 downto 0) := "00";
    signal fb_sync  : std_logic_vector(1 downto 0) := "00";

    -- Rising edge detectors
    signal ref_rise : std_logic;
    signal fb_rise  : std_logic;

    -- PFD state flip-flops
    signal up_q     : std_logic := '0';
    signal dn_q     : std_logic := '0';

    -- Anti-deadzone reset (both high)
    signal pfd_reset : std_logic;
begin
    ------------------------------------------------------------------
    -- Input synchronizers
    ------------------------------------------------------------------
    sync_proc: process(clk)
    begin
        if rising_edge(clk) then
            if rst_n = '1' then
                ref_sync <= "00";
                fb_sync  <= "00";
            else
                ref_sync <= ref_sync(0) & ref_in;
                fb_sync  <= fb_sync(0)  & fb_in;
            end if;
        end if;
    end process;

    ref_rise <= ref_sync(1) and not ref_sync(0);
    fb_rise  <= fb_sync(1)  and not fb_sync(0);

    pfd_reset <= up_q and dn_q;

    ------------------------------------------------------------------
    -- PFD logic: UP/DN stay high until opposite edge resets via both high
    ------------------------------------------------------------------
    pfd_proc: process(clk)
    begin
        if rising_edge(clk) then
            if rst_n = '1' then
                up_q <= '0';
                dn_q <= '0';
            else
                if pfd_reset = '1' then
                    up_q <= '0';
                    dn_q <= '0';
                else
                    if ref_rise = '1' then
                        up_q <= '1';
                    end if;
                    if fb_rise = '1' then
                        dn_q <= '1';
                    end if;
                end if;
            end if;
        end if;
    end process;

    up <= up_q;
    dn <= dn_q;
end architecture;