----------------------------------------------
-- MSS copyright 1999-2002
--	File: BER_MEASUREMENT2.VHD
-- Authors: 
--		Alain Zarembowitch / MSS
-- Inheritance: BER_MEASUREMENT.VHD v0.001 8-28-01
-- Edit date: 2-6-02
-- Revision: 0.002
--
-- Bit error measurement. Count actual errors over 32 synchronization frames of 
-- 32-bits each (1024 bits).
-- The BER measurement is updated every 0.57 seconds
--
-- Rev 0.002 AZ 2-6-02
-- ComBlock adaptation. Frame length is programmable.
----------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity BER_MEASUREMENT2 is
    port (
    	ASYNC_RESET: in  std_logic;
			-- asynchronous reset active high for initialization to well known state prior to power up
 		CLK: in std_logic;	
			-- reference clock, synchronous design
      SOF: in std_logic;
		BIT_CLK: in std_logic;
      DATA: in std_logic;
		FRAME_LENGTH: in std_logic_vector(12 downto 0);
			-- unique word period.

		BER: out std_logic_vector(16 downto 0)
			-- bit error rate, measured over 1024 bits .

	);
end entity;

architecture BEHAVIOR of BER_MEASUREMENT2 is
-----------------------------------------------------------------
-- COMPONENTS
-----------------------------------------------------------------
-----------------------------------------------------------------
-- SIGNALS
-----------------------------------------------------------------
-- Suffix _D denotes one CLK delayed version of the net with the same name.
signal FRAME_COUNT: std_logic_vector(12 downto 0);	-- range 0- - 31 inclusive
constant SYNC32: std_logic_vector(31 downto 0) := "01100110011111011111000001011010";
-- sequence is bit reversed 5A 0F BE 66
signal BIT_COUNT: integer range 0 to 4127;
signal BER_LOCAL: std_logic_vector(16 downto 0);          
signal FRAME_LENGTH_MINUSONE: std_logic_vector(12 downto 0);
-----------------------------------------------------------------
-- IMPLEMENTATION
-----------------------------------------------------------------
begin 

-- Count number of frames
FRAME_COUNTER_001: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then 
		FRAME_COUNT <= (others => '0');
	elsif rising_edge(CLK) then
		if(SOF = '1') and (BIT_CLK = '1') then
			if(FRAME_COUNT = 31) then
				-- modulo 32 (1024 bits)
				FRAME_COUNT <= (others => '0');
			else
				FRAME_COUNT <= FRAME_COUNT + 1;
		  	end if;
	  	end if;
	end if;
end process; 

-- count bits within a frame
-- Unique word is at bit 0-31          
FRAME_LENGTH_MINUSONE <= FRAME_LENGTH + "1111111111111";
BIT_COUNTER_001: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then 
		BIT_COUNT <= 0;
	elsif rising_edge(CLK) then
		if(SOF = '1') and (BIT_CLK = '1') then
			BIT_COUNT <= 33;	-- just read bit 32
		elsif(BIT_CLK = '1') then
			-- modulo 4096 + 32 = 4128
			if(BIT_COUNT = FRAME_LENGTH_MINUSONE) then
				BIT_COUNT <= 0;
			else
				BIT_COUNT <= BIT_COUNT + 1;
		  	end if;
	  	end if;
	end if;
end process; 

ERROR_COUNT_001: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then 
		BER_LOCAL <= (others => '0');
		BER <= (others => '0');
	elsif rising_edge(CLK) then
		if(SOF = '1') and (BIT_CLK = '1') and (FRAME_COUNT = 31) then
			-- just completed computing errors over 1024 bits
			-- reset counter and latch previous results for output.
			BER_LOCAL <= (others => '0');
			BER <= BER_LOCAL;
		elsif(BIT_CLK = '1') and (BIT_COUNT < 32) then
			if(DATA /= SYNC32(BIT_COUNT)) then
				BER_LOCAL <= BER_LOCAL + 1;
			end if;
	  	end if;
 	end if;
end process;

end  BEHAVIOR;
