library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

use work.linear_block_package.all;


-- The word, "word" is reserved for encoded data 24 bits
-- The word. "data" is reserved for non-encoded data 12 btis
entity linear_block_decoder is
    port(
            clk:         in  std_logic;
            reset:       in  std_logic;
            data_in:     in  word_vector;
            decoded_out: out data_vector;
            errorDecoded_out:out std_logic
        );
end linear_block_decoder;



architecture behavioral of linear_block_decoder is
    signal syndrome:    word_vector :=(others =>'0');
    signal errorVector: data_vector :=(others =>'0');
    signal sindromexB:  data_vector :=(others =>'0');
    signal hammingW:    integer := 0;
    -- fms contral signals 
    type fms is (idle,step1,step2,step3,step4,deco,fail);
    signal deco_state: fms;
    signal deco_next : fms;
    -- output control signals
    signal decoded_buf :     data_vector :=(others=>'0');
    signal decoded_buf_next: data_vector :=(others=>'0');
    -- error when it is not possible to decode
    signal errorDecoded: std_logic:='0';



begin
-- decoder finite state machie
    deco_fms: process(clk)
    begin 
        if (reset='1') then
            deco_state <= idle;
            errorDecoded <= '0';
        elsif(clk'event and clk='1') then
            deco_state <= deco_next;
        end if;
    end process;

-- decoded output
    deco_buffer: process(clk)
    begin
        if(reset='1') then
            decoded_buf <= zeros12;
        elsif(clk'event and clk='1') then
            decoded_buf <= decoded_buf_next;
        end if;
    end process;
        
-- decoder logic
    deco_logic: process(deco_state,data_in)
    begin

        case deco_state is
            when idle => 
                if (data_in /= zeros24) then
                    deco_next <= step1;
                else
                    deco_next <= idle;
                end if;
            when step1 =>
                -- calc syndrome and hamming(syndrome)
                if (hammingW<=3) then 
                    deco_next <= deco;
                else
                    deco_next <= step2;
                end if;

            when step2 =>
                -- calc error and hammingW(error)
                if (hammingW<=2) then 
                    deco_next <= deco;
                else
                    deco_next <= step3;
                end if;    

            when step3 =>
                -- syndromexB and hammingW(syndromeB)
                if (hammingW<=3) then 
                    deco_next <= deco;
                else
                    deco_next <= step4;
                end if;
                            
            when step4 =>
                -- (Beta*B+rowi) and hammingW
                if (hammingW <= 3) then 
                    deco_next <= deco;
                else 
                    deco_next <= fail;
                end if;

            when deco  =>
                deco_next <= idle;

            when fail  =>
                deco_next <= idle;
       end case;

    end process;

-- output logic
    output_logic: process(deco_state)
    begin
        decoded_buf_next <= zeros12;

        case deco_next is
            when idle  =>
            when step1 =>
            when step2 =>
            when step3 =>
            when step4 =>

            when deco  =>
                --decoded_buf_next <= 
                errorDecoded     <= '0';  -- no error
            when fail  =>
                decoded_buf_next <= zeros12;
                errorDecoded     <= '1';
        end case;
    end process;

-- output
    decoded_out <= decoded_buf;

end behavioral;
