library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity LiFi_Transmiter_Top is
generic(
    INFREQ          :       integer := 100_000_000;
    LiFiFreq        :       integer := 3_000 -- 3 kHz
);
Port ( 
        clk             :IN         STD_LOGIC;
        DataIn          :IN         STD_LOGIC_VECTOR(31 downto 0);
        DataEnabled     :IN         STD_LOGIC;
        
        TX              :OUT        STD_LOGIC;
        
        read_en : out           std_logic
);
end LiFi_Transmiter_Top;

architecture Behavioral of LiFi_Transmiter_Top is

component LiFi_Transmiter
Port ( 
        clkLiFi         :IN         STD_LOGIC;
        DataIn          :IN         STD_LOGIC_VECTOR(31 downto 0);
        
        Finished        :OUT        STD_LOGIC := '1';
        TX              :OUT        STD_LOGIC;
        
        read_en         :out       std_logic:='0'
);
end component;

component SetResetHold
Port (
        clk         :IN     STD_LOGIC;
        Set         :IN     STD_LOGIC;
        Reset       :IN     STD_LOGIC;
        Result      :OUT    STD_LOGIC := '0'
);
end component;

component clk_div_reset
generic (
    INFREQ                : integer := INFREQ;
    OUTFREQ               : integer := LiFiFreq/4
);	
Port (
    clk             :IN     STD_LOGIC;
    reset           :IN     STD_LOGIC;
    reset_seen      :OUT    STD_LOGIC;
    clkOut          :OUT    STD_LOGIC
);
end component;

signal senderFinished       : STD_LOGIC := '0';
signal resetDivider         : STD_LOGIC := '0';
signal clkLiFi              : STD_LOGIC := '0';

signal TxNoManchester       : STD_LOGIC;

begin

clockGenerator: clk_div_reset
Port map(
    clk             => clk,
    reset           => resetDivider,
    reset_seen      => open,
    clkOut          => clkLiFi
);

Transmitter: LiFi_Transmiter
Port map ( 
        clkLiFi         => clkLiFi,
        DataIn          => Datain,
        
        Finished        => senderFinished,
        TX              => TxNoManchester,
        
        read_en=> read_en
);

TX <= (TxNoManchester XOR not clkLiFi) when senderFinished = '0' else '0';

holder: SetResetHold
Port map(
        clk         => clk,
        Set         => DataEnabled,
        Reset       => senderFinished,
        Result      => resetDivider
);

end Behavioral;
