----------------------------------------------------------------------------------
-- Company: 
-- Engineer: David Makowka
-- 
-- Create Date: 11/15/2019 03:15:18 PM
-- Design Name: 
-- Module Name: reciever_vhdl - Behavioral
-- Project Name: 
-- Target Devices: 
-- Tool Versions: 
-- Description: 
-- 
-- Dependencies: 
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
----------------------------------------------------------------------------------


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

entity reciever_vhdl is
    Port ( clk              : in STD_LOGIC;
           reset            : in STD_LOGIC;
           RxD              : in STD_LOGIC;
           NumbRegInBCD     : out STD_LOGIC_VECTOR (15 downto 0));
end reciever_vhdl;

architecture Behavioral of reciever_vhdl is
    
    -------------------------------------------------------------------------------
    --                  CONSTANTS
    -------------------------------------------------------------------------------
    
    constant c_ClkFrequency       : natural := 100000000;
    constant c_BaudRate           : natural := 9600;
    constant c_DivSample          : natural := 4;
    constant c_DivCounter         : natural := c_ClkFrequency/(c_BaudRate*c_DivSample);     -- 2604
    constant c_MidSample          : natural := c_DivSample/2;                               -- This is the moment we want to sample
    constant c_DivBit             : natural := 10;
    
    -------------------------------------------------------------------------------
    --                  SIGNALS
    -------------------------------------------------------------------------------
    
    -- REGISTER FOR RAW DATA WITHOUT START AND STOP BIT
    signal s_RxAsciiCode          : std_logic_vector (7 downto 0) := "00000000";
    
    -- STATE MACHINE ---------------------------------------------------------------
    signal s_state                : std_logic := '0';
    signal s_nextState            : std_logic := '0';
   
    -- STATE MACHINE 2 STATES AND AUXILIARY SIGNALS ---------------------------------
    signal s_state_2              : std_logic_vector(2  downto 0) := "000";
    signal s_nextState_2          : std_logic_vector(2  downto 0) := "000";
    --Number which is going to be putted into shift register
    signal s_numbInBcd            : std_logic_vector(3  downto 0);  
    --Last 4 BCD numbers, which goes to display
    signal s_numbRegInBcd         : std_logic_vector(15 downto 0);
    signal s_shiftBCDReg          : std_logic;
   
    -- BAUDRATE COUNTER ------------------------------------------------------------
    signal s_baudRateCounter      : natural range 0 to 10416;
       
    -- REGISTER FOR DATA -----------------------------------------------------------
    signal s_shiftInputBit        : std_logic;
    signal s_RxShiftRegister      : std_logic_vector(9 downto 0);
    
    -- BIT COUNTER -----------------------------------------------------------------
    signal s_ClearBitCounter      : std_logic;
    signal s_IncBitCounter        : std_logic;
    signal s_bitCounter           : natural range 0 to 9;
    
    -- SAMPLE COUNTER --------------------------------------------------------------
    signal s_ClearSampleCounter   : std_logic;
    signal s_IncSampleCounter     : std_logic;
    signal s_sampleCounter        : natural range 0 to 4;
    
    signal s_messageBuffer        : std_logic_vector(15 downto 0);

begin
    
    NumbRegInBCD <= s_numbRegInBcd;
    
    with s_RxAsciiCode select s_numbInBcd <=
        "0000" when "00110000",
        "0001" when "00110001",
        "0010" when "00110010",
        "0011" when "00110011",
        "0100" when "00110100",
        "0101" when "00110101",
        "0110" when "00110110",
        "0111" when "00110111",
        "1000" when "00111000",
        "1001" when "00111001",
        "1010" when "00111010",
        "0000" when others;

    --This process cut start and end bit from recieved data
    Process(clk)
    begin
        if rising_edge(clk) then
            s_RxAsciiCode <= s_RxShiftRegister(8 downto 1);
            
        end if;
    end process;
    
    --This process is cool
    Process(clk)
    begin
        if rising_edge(clk) then
            if (reset = '1') then
                s_state                 <= '0';
                s_bitCounter            <= 0;
                s_baudRateCounter       <= 0;
                s_sampleCounter         <= 0;
            else
                s_baudRateCounter <= s_baudRateCounter + 1;     
                if (s_baudRateCounter >= c_DivCounter - 1) then
                    s_state             <= s_nextState;
                    s_baudRateCounter   <= 0;
                    
                    -- SHIFTING INPUT DATA TO INPUT REGISTER
                    if (s_shiftInputBit = '1')        then  s_RxShiftRegister <= RxD & s_RxShiftRegister(9 downto 1);       end if;--right shift
                    if (s_shiftBCDReg = '1')          then  s_numbRegInBcd <= s_numbRegInBcd(11 downto 0) & s_numbInBcd;    end if;--right shift
                    -- CLEARING COUNTERS
                    if (s_ClearBitCounter = '1')      then s_bitCounter <= 0;                                               end if;
                    if (s_ClearSampleCounter = '1')   then s_sampleCounter <= 0;                                            end if;
                    -- INCREMENTING COUNTERS
                    if (s_IncBitCounter = '1')        then s_bitCounter <= s_bitCounter + 1;                                end if;
                    if (s_IncSampleCounter = '1')     then s_sampleCounter <= s_sampleCounter + 1;                          end if; 
                end if;       
            end if;
        end if;
    end process;
    
    Process(clk)
    begin
        if rising_edge(clk) then
            -- WHEN THERE IS NOT LATER ASSIGN DIFFRENT VALUE SIGNALS ARE IN THERE DEFAULT VALUES
            s_shiftInputBit                   <= '0';                                       
            s_shiftBCDReg                     <= '0';
             
            s_ClearBitCounter                 <= '0';
            s_ClearSampleCounter              <= '0';
            
            s_IncBitCounter                   <= '0';
            s_IncSampleCounter                <= '0';
            
            s_nextstate                       <= '0';
                
             case (s_state) is
                -- IDLE STATE -------------------------------------------------------------------------------------------------
                 when '0' =>
                    if (RxD = '0') then
                        s_nextState           <= '1';
                        s_ClearBitCounter     <= '1';
                        s_ClearSampleCounter  <= '1';
                    else
                        s_nextState           <= '0';
                    end if;
                    
                 -- RECEIVING STATE --------------------------------------------------------------------------------------------
                 when '1' =>
                    s_nextState <= '1';                              -- stay recieving
                    
                    if (s_sampleCounter = c_MidSample-1) then        -- sample counter is in half
                        s_shiftInputBit <= '1';                      -- we store a value from RxD by shifting the storing register
                    end if;
                                                
                    if (s_sampleCounter = c_DivSample - 1) then      -- sampleCounter is full
                        if (s_bitCounter = c_DivBit - 1) then        -- all bits were send
                            s_nextState         <= '0';
                            s_shiftBCDReg       <= '1';
                        end if;
                        s_IncBitCounter         <= '1';
                        s_ClearSampleCounter    <= '1';
                    else
                        s_IncSampleCounter      <= '1';
                    end if; 
                when others => s_nextState      <= '0';
            end case;
        end if;                                                      --rising edge if
    end process;
    


end Behavioral;
