-- prbs_checker.vhd -- VHDL-93 synthesizable PRBS-16 checker with order and frame loss detection. -- Provides: sync flag, error counter (data integrity), loss counter (skipped frames). -- All outputs are marked with "keep" attribute. library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity prbs_checker is generic ( SEED : std_logic_vector(15 downto 0) := x"ACE1"; -- initial expected value SEARCH_MAX : natural := 8 -- max frames to search ahead for loss detection ); port ( clk : in std_logic; rst : in std_logic; -- synchronous reset, active '1' enable : in std_logic; -- advance/check when '1' data_in : in std_logic_vector(15 downto 0); -- received 16-bit frame sync : out std_logic; -- '1' when synchronized (observing correct transitions) error_count : out std_logic_vector(31 downto 0); -- counts data integrity errors (no match in window) loss_count : out std_logic_vector(31 downto 0) -- counts lost frames inferred by forward matches ); end entity prbs_checker; architecture rtl of prbs_checker is -- Keep attribute on outputs attribute keep : string; attribute keep of sync : signal is "true"; attribute keep of error_count : signal is "true"; attribute keep of loss_count : signal is "true"; -- Internal expected PRBS state and status signal expected : std_logic_vector(15 downto 0) := (others => '0'); signal sync_reg : std_logic := '0'; signal err_cnt : unsigned(31 downto 0) := (others => '0'); signal loss_cnt : unsigned(31 downto 0) := (others => '0'); -- Simple sync state machine: require one correct transition to assert sync type sync_state_t is (UNSYNC, SYNCED_WAIT, SYNCED); signal sync_state : sync_state_t := UNSYNC; -- LFSR next-state function (same polynomial and mapping as transmitter) function lfsr16_next(s : std_logic_vector(15 downto 0)) return std_logic_vector is variable fb : std_logic; variable n : std_logic_vector(15 downto 0); begin fb := s(0) xor s(2) xor s(3) xor s(5); n := fb & s(15 downto 1); return n; end function; -- Forward search: find how many steps ahead from expected matches data_in. -- Returns 0 if immediate next state matches; k in [1..SEARCH_MAX] if match found k steps ahead; -- returns SEARCH_MAX+1 if no match within window. function search_ahead(cur : std_logic_vector(15 downto 0); target : std_logic_vector(15 downto 0); max_steps : natural) return natural is variable probe : std_logic_vector(15 downto 0); begin probe := lfsr16_next(cur); if probe = target then return 0; end if; for k in 1 to max_steps loop probe := lfsr16_next(probe); if probe = target then return k; end if; end loop; return max_steps + 1; end function; begin -- Drive outputs sync <= sync_reg; error_count <= std_logic_vector(err_cnt); loss_count <= std_logic_vector(loss_cnt); -- Main checker process process(clk) variable ahead : natural; begin if rising_edge(clk) then if rst = '1' then expected <= SEED; sync_state <= UNSYNC; sync_reg <= '0'; err_cnt <= (others => '0'); loss_cnt <= (others => '0'); else if enable = '1' then case sync_state is when UNSYNC => -- Load current sample as baseline; wait for a correct transition to assert sync. expected <= data_in; sync_reg <= '0'; sync_state <= SYNCED_WAIT; when SYNCED_WAIT => -- Confirm that the next input matches lfsr_next(expected). ahead := search_ahead(expected, data_in, 0); -- only check immediate next if ahead = 0 then expected <= data_in; sync_reg <= '1'; sync_state <= SYNCED; else -- Stay in wait; re-baseline to current sample to improve acquisition on changing inputs. expected <= data_in; sync_reg <= '0'; -- remain in SYNCED_WAIT end if; when SYNCED => -- In-sync: check order and detect frame loss. ahead := search_ahead(expected, data_in, SEARCH_MAX); if ahead = 0 then -- Correct next frame expected <= data_in; sync_reg <= '1'; elsif ahead <= SEARCH_MAX then -- Match found ahead: count skipped frames and fast-forward expected loss_cnt <= loss_cnt + to_unsigned(ahead, loss_cnt'length); expected <= data_in; sync_reg <= '1'; else -- No match within window: data integrity error; drop sync and reacquire err_cnt <= err_cnt + 1; sync_reg <= '0'; sync_state <= UNSYNC; -- expected will be reloaded in UNSYNC end if; end case; end if; end if; end if; end process; end architecture rtl;