architecture RTL of Hamming8 is

 begin

   process (DataOut,DataIn,CheckIn)
      variable PgenL,PgenH:         Std_Logic_Vector(0 to 3);  -- Generated parity
      variable SyndL,SyndH:         Std_Logic_Vector(0 to 3);  -- Syndrome
      variable FlipL,FlipH:         Std_Logic_Vector(0 to 3);  -- Bits to invert
      variable ChipL,ChipH:         Std_Logic_Vector(0 to 3);  -- Errors in parity

   begin
      -- Check bit generator
      PgenL(0) := not (DataIn(0) xor DataIn(1) xor DataIn(2));
      PgenL(1) :=      DataIn(0) xor DataIn(1) xor DataIn(3);
      PgenL(2) := not (DataIn(0) xor DataIn(2) xor DataIn(3));
      PgenL(3) :=      DataIn(1) xor DataIn(2) xor DataIn(3);

      PgenH(0) := not (DataIn(4) xor DataIn(5) xor DataIn(6));
      PgenH(1) :=      DataIn(4) xor DataIn(5) xor DataIn(7);
      PgenH(2) := not (DataIn(4) xor DataIn(6) xor DataIn(7));
      PgenH(3) :=      DataIn(5) xor DataIn(6) xor DataIn(7);

      -- Syndrome bit generator
      SyndL(0) := PgenL(0) xor not CheckIn(0);
      SyndL(1) := PgenL(1) xor not CheckIn(1);
      SyndL(2) := PgenL(2) xor     CheckIn(2);
      SyndL(3) := PgenL(3) xor     CheckIn(3);

      SyndH(0) := PgenH(0) xor not CheckIn(4);
      SyndH(1) := PgenH(1) xor not CheckIn(5);
      SyndH(2) := PgenH(2) xor     CheckIn(6);
      SyndH(3) := PgenH(3) xor     CheckIn(7);

      -- Bit corrector
      if SyndL="1110" then
         FlipL(0) := '1';
      else
         FlipL(0) := '0';
      end if;
      if SyndL="1101" then
         FlipL(1) := '1';
      else
         FlipL(1) := '0';
      end if;
      if SyndL="1011" then
         FlipL(2) := '1';
      else
         FlipL(2) := '0';
      end if;
      if SyndL="0111" then
         FlipL(3) := '1';
      else
         FlipL(3) := '0';
      end if;

      if SyndH="1110" then
         FlipH(0) := '1';
      else
         FlipH(0) := '0';
      end if;
      if SyndH="1101" then
         FlipH(1) := '1';
      else
         FlipH(1) := '0';
      end if;
      if SyndH="1011" then
         FlipH(2) := '1';
      else
         FlipH(2) := '0';
      end if;
      if SyndH="0111" then
         FlipH(3) := '1';
      else
         FlipH(3) := '0';
      end if;

      -- Single error in check bits
      if SyndL="0001" then
         ChipL(0) := '1';
      else
         ChipL(0) := '0';
      end if;
      if SyndL="0010" then
         ChipL(1) := '1';
      else
         ChipL(1) := '0';
      end if;
      if SyndL="0100" then
         ChipL(2) := '1';
      else
         ChipL(2) := '0';
      end if;
      if SyndL="1000" then
         ChipL(3) := '1';
      else
         ChipL(3) := '0';
      end if;

      if SyndH="0001" then
         ChipH(0) := '1';
      else
         ChipH(0) := '0';
      end if;
      if SyndH="0010" then
         ChipH(1) := '1';
      else
         ChipH(1) := '0';
      end if;
      if SyndH="0100" then
         ChipH(2) := '1';
      else
         ChipH(2) := '0';
      end if;
      if SyndH="1000" then
         ChipH(3) := '1';
      else
         ChipH(3) := '0';
      end if;

      -- Corrected data
      DataCorr(0) < = DataIn(0) xor FlipL(0);
      DataCorr(1) < = DataIn(1) xor FlipL(1);
      DataCorr(2) < = DataIn(2) xor FlipL(2);
      DataCorr(3) < = DataIn(3) xor FlipL(3);

      DataCorr(4) < = DataIn(4) xor FlipH(0);
      DataCorr(5) < = DataIn(5) xor FlipH(1);
      DataCorr(6) < = DataIn(6) xor FlipH(2);
      DataCorr(7) < = DataIn(7) xor FlipH(3);

      -- Check bits
      CheckOut(0) < = not (not (DataOut(0) xor DataOut(1) xor DataOut(2)));
      CheckOut(1) < = not (     DataOut(0) xor DataOut(1) xor DataOut(3));
      CheckOut(2) < =     (not (DataOut(0) xor DataOut(2) xor DataOut(3)));
      CheckOut(3) < =     (     DataOut(1) xor DataOut(2) xor DataOut(3));

      CheckOut(4) < = not (not (DataOut(4) xor DataOut(5) xor DataOut(6)));
      CheckOut(5) < = not (     DataOut(4) xor DataOut(5) xor DataOut(7));
      CheckOut(6) < =     (not (DataOut(4) xor DataOut(6) xor DataOut(7)));
      CheckOut(7) < =     (     DataOut(5) xor DataOut(6) xor DataOut(7));

      -- Single correctable error flag
      SingleErr   < = (FlipL(0) or FlipL(1) or FlipL(2) or FlipL(3)) xor
                     (FlipH(0) or FlipH(1) or FlipH(2) or FlipH(3)) xor
                     (ChipL(0) or ChipL(1) or ChipL(2) or ChipL(3)) xor
                     (ChipH(0) or ChipH(1) or ChipH(2) or ChipH(3));

      -- double correctable error flag
      DoubleErr   < = ((FlipL(0) or FlipL(1) or FlipL(2) or FlipL(3)) or
                      (ChipL(0) or ChipL(1) or ChipL(2) or ChipL(3))) and

                     ((FlipH(0) or FlipH(1) or FlipH(2) or FlipH(3)) or
                      (ChipH(0) or ChipH(1) or ChipH(2) or ChipH(3)));

      -- Uncorrectable error flag
      if SyndL="0011" or SyndL="0101" or
         SyndL="0110" or SyndL="1001" or
         SyndL="1010" or SyndL="1100" or
         SyndL="1111" or
         SyndH="0011" or SyndH="0101" or
         SyndH="0110" or SyndH="1001" or
         SyndH="1010" or SyndH="1100" or
         SyndH="1111" then
         MultipleErr    < = '1';
      else
         MultipleErr    < = '0';
      end if;

   end process;
 end RTL;