-- Synopsys Design Contest 2002
-- errorcnt.vhd
-- 2001/September/13th
-- TASK: Differencial Cyclic Code FEC
-- Copyright by  Tom Wada@Univ. of the Ryukyus

library IEEE;
use IEEE.STD_LOGIC_1164.all, IEEE.NUMERIC_STD.all;

entity ERRORCNT is
    port (START    : in  std_logic;
	  RB       : in  std_logic;
	  START2   : in  std_logic;
	  RBEC     : in  std_logic;
	  ERRCNT   : out unsigned(7 downto 0);
	  RESET    : in  std_logic;
	  CLK      : in  std_logic );
end entity ERRORCNT;

architecture RTL of ERRORCNT is

-- phase counter
signal phase   : unsigned (4 downto 0);
-- enable signal
signal en      : std_logic;
-- 21 bit signal shift register
signal data    : unsigned (20 downto 0);
-- RBEC input register
signal rbecin  : std_logic;
-- RBEC phase counter
signal phase2  : unsigned (4 downto 0);
-- enable2 signal
signal en2      : std_logic;
-- 8bit error counter
signal counter : unsigned (7 downto 0);

begin
---------------------------------------------
-- phase generation
-- count 20 downto 0
---------------------------------------------
PHASE_GEN: process (CLK, RESET) begin
    if (RESET='1') then phase <= "00000"; 
    elsif rising_edge(CLK) then
	if (START='1') then phase <= "10100"; -- set 20
	elsif (phase="00000") then phase <= "00000";
	else  phase <= phase -1;
	end if;
    end if;
end process PHASE_GEN;
---------------------------------------------
-- ENABLE generation, COMBINATIONAL LOGIC
-- EN is high while START=1 or phase is not 0
---------------------------------------------
EN_GEN: process (START, phase) begin
    if(START='1' or phase /= "00000") then en <='1';
    else en <='0';
    end if;
end process EN_GEN;
---------------------------------------------
-- 21 bit shift register
---------------------------------------------
SHIFT_REG: process(CLK, RESET) begin
    if (RESET='1') then data <= (others=>'0');
    elsif rising_edge(CLK) then
	if (en='1') then
	      data <= data(19 downto 0) & RB;
	end if;
    end if;
end process SHIFT_REG;
---------------------------------------------
-- PHASE2 generation
---------------------------------------------
PHASE2_GEN: process(CLK, RESET) begin
    if (RESET='1') then phase2 <= "00000";
    elsif rising_edge(CLK) then
	if (START2='1') then phase2 <= "10100"; -- set 20
        elsif (phase2="00000") then phase2 <= "00000";
	else phase2 <= phase2 -1;
	end if;
    end if;
end process PHASE2_GEN;
---------------------------------------------
-- ENABLE2 generation
-- EN2 is high while START2=1 or phase is not 0
---------------------------------------------
EN2_GEN: process (CLK, RESET) begin
    if (RESET='1') then en2 <='0';
    elsif rising_edge(CLK) then
        if(START2='1' or phase2 /= "00000") then en2 <='1';
        else en2 <='0';
        end if;
    end if;
end process EN2_GEN;
---------------------------------------------
-- RBECIN input register
---------------------------------------------
INPUT_REG: process(CLK, RESET) begin
    if (RESET='1') then rbecin <= '0';
    elsif rising_edge(CLK) then
        rbecin <= RBEC;
    end if;
end process INPUT_REG;
---------------------------------------------
-- error counter
---------------------------------------------
ERR_CNT: process(CLK,RESET) begin
    if (RESET='1') then counter <= "00000000";
    elsif rising_edge(CLK) then
	if (en2='1' and data(TO_INTEGER(phase2)) /= rbecin) then
	    counter <= counter+1;
        end if;
    end if;
end process ERR_CNT;

ERRCNT <= counter;

end architecture RTL;
