-- ** EDAC Decoder **
--
-- Description:     A generic EDAC decoder of the Extended Hamming Code for single-error
--                  correction and double-error detection (SEC-DED)
--  
-- Project:         UMEL_ŠB
-- File name:       edac_decoder.vhd
-- Creation date:   May 2, 2016
--
-- Institution:     Brno University of Technology, FEEC UMEL
-- Author:          Martin Stava
-- Author's e-mail: stavam1@feec.vutbr.cz
--
--
-- Modified by:              Jan Bares
-- Modification Date:        June 1, 2016
-- Modification File name:   decoder.rtl.vhd
----------------------------------------------------------------------------------------

-- ------------------------------------------------------------------------ --
--                                                                Libraries --
-- ------------------------------------------------------------------------ --
library ieee;
use ieee.std_logic_1164.all;

library work;
use work.hamm_rom_pkg.all;
-- ------------------------------------------------------------------------ --
--                                                                   Entity --
-- ------------------------------------------------------------------------ --
entity decoder is
  port (
        DATA_IN : in std_logic_vector (c_ENCODED_DATA_WIDTH-1 downto 0);
        DATA_OUT     : out std_logic_vector (c_INF_DATA_WIDTH-1 downto 0);
        ERR_DET : out std_logic;
        ERR_COR  : out std_logic
       );
end decoder;


-- ------------------------------------------------------------------------ --
--                                                             Architecture --
-- ------------------------------------------------------------------------ --
architecture rtl of decoder is

  -- ---------------------------------------------------------------------------
  --  General constants
  -- ---------------------------------------------------------------------------
  constant c_NULL_SYN        : std_logic_vector (c_CHECK_DATA_WIDTH-1 downto 0) := (others => '0');  

  -- ---------------------------------------------------------------------------
  -- Signals
  -- ---------------------------------------------------------------------------
  signal syndrome          : std_logic_vector (c_CHECK_DATA_WIDTH-1 downto 0);
  signal correction        : std_logic_vector (c_INF_DATA_WIDTH-1 downto 0);
  signal no_err            : std_logic;
  signal correctable_error : std_logic;

begin
  syndrome_gen:
  for i in c_CHECK_DATA_WIDTH-1 downto 0 generate

    p_syn_bit: process (DATA_IN)
      variable p : std_logic;
    begin
      p := '0';
      for j in c_ENCODED_DATA_WIDTH-1 downto 0 loop
        if c_H_EXT(i)(j) = '1' then
          p := p xor DATA_IN(j);
        end if;
      end loop;

      syndrome(i) <= p; 

    end process;


  end generate;

  --

  syndrome_dec:
  for i in c_ENCODED_DATA_WIDTH-1 downto c_CHECK_DATA_WIDTH generate

    process (syndrome)
		variable h_col : std_logic_vector (c_CHECK_DATA_WIDTH-2 downto 0);
    begin

      for j in c_CHECK_DATA_WIDTH-1 downto 1 loop
        h_col(j-1) := c_H_EXT(j)(i);
      end loop;

      if h_col = syndrome (c_CHECK_DATA_WIDTH-1 downto 1) then
        correction(i-c_CHECK_DATA_WIDTH) <= '1';
      else
        correction(i-c_CHECK_DATA_WIDTH) <= '0';
      end if;

    end process;

  end generate;

  --

  no_err <= '1' when syndrome = c_NULL_SYN else
            '0'; 
  p_corr_err: process (syndrome)
    variable p : std_logic;
  begin
    p := '0';
    for j in c_CHECK_DATA_WIDTH-1 downto 0 loop
      if syndrome(j) = '1' then
        p := not p;
      end if;
    end loop;

  correctable_error <= p; 

  end process;


  -- ---------------------------------------------------------------------- --
  --                                                     output assignments --
  -- ---------------------------------------------------------------------- --

  DATA_OUT <= DATA_IN (c_ENCODED_DATA_WIDTH-1 downto c_CHECK_DATA_WIDTH) xor correction;
  ERR_COR <= correctable_error;
  ERR_DET  <= (not no_err) and (not correctable_error);

end rtl;
