library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;

library std;
use std.textio.all;

entity tb_combpm_protocol_electron is
end entity;

architecture testbench of tb_combpm_protocol_electron is

    file file_input : text open read_mode is "input.txt";

    signal tb_clk : std_logic := '0';
    signal tb_rstn : std_logic := '1';

    signal tb_gt_datarx : std_logic_vector(15 downto 0);
    signal tb_gt_datatx : std_logic_vector(15 downto 0);
    signal tb_gt_powergood : std_logic;
    signal tb_gt_qplllock : std_logic;
    signal tb_gt_txclkactive : std_logic;
    signal tb_gt_rxclkactive : std_logic;
    signal tb_gt_txresetdone : std_logic;
    signal tb_gt_rxresetdone : std_logic;
    signal tb_gt_rxcdrlock : std_logic;
    signal tb_gt_rxbyteisaligned : std_logic;
    signal tb_gt_rxbyterealign : std_logic;
    signal tb_gt_rxcommadet : std_logic;
    signal tb_gt_txfault : std_logic;
    signal tb_gt_rxlos : std_logic;
    signal tb_gt_modabs : std_logic;
    signal tb_gt_rstall : std_logic;
    signal tb_gt_rxcommadeten : std_logic;
    signal tb_gt_txdisable : std_logic;

    signal tb_m_axi_tid : std_logic_vector(0 downto 0);
    signal tb_m_axi_tdest : std_logic_vector(9 downto 0);
    signal tb_m_axi_tdata : std_logic_vector(127 downto 0);
    signal tb_m_axi_tstrb : std_logic_vector(15 downto 0);
    signal tb_m_axi_tkeep : std_logic_vector(15 downto 0);
    signal tb_m_axi_tlast : std_logic;
    signal tb_m_axi_tuser : std_logic_vector(0 downto 0);
    signal tb_m_axi_tvalid : std_logic;
    signal tb_m_axi_tready : std_logic;

    signal tb_s_axi_clk     : std_logic;
    signal tb_s_axi_resetn  : std_logic;
    signal tb_s_axi_awaddr  : std_logic_vector(7 downto 0);
    signal tb_s_axi_awprot  : std_logic_vector(2 downto 0);
    signal tb_s_axi_awvalid : std_logic;
    signal tb_s_axi_awready : std_logic;
    signal tb_s_axi_wdata   : std_logic_vector(32-1 downto 0);
    signal tb_s_axi_wstrb   : std_logic_vector(32/8-1 downto 0);
    signal tb_s_axi_wvalid  : std_logic;
    signal tb_s_axi_wready  : std_logic;
    signal tb_s_axi_bresp   : std_logic_vector(1 downto 0);
    signal tb_s_axi_bvalid  : std_logic;
    signal tb_s_axi_bready  : std_logic;
    signal tb_s_axi_araddr  : std_logic_vector(7 downto 0);
    signal tb_s_axi_arprot  : std_logic_vector(2 downto 0);
    signal tb_s_axi_arvalid : std_logic;
    signal tb_s_axi_arready : std_logic;
    signal tb_s_axi_rdata   : std_logic_vector(32-1 downto 0);
    signal tb_s_axi_rresp   : std_logic_vector(1 downto 0);
    signal tb_s_axi_rvalid  : std_logic;
    signal tb_s_axi_rready  : std_logic;

    signal test_done : boolean := False;

begin

    -----------------------
    -- DEFAULT CONNEXION --
    -----------------------
    tb_m_axi_tready <= '1';
    tb_gt_powergood <= '1';
    tb_gt_qplllock <= '1';
    tb_gt_txclkactive <= '1';
    tb_gt_rxclkactive <= '1';
    tb_gt_txresetdone <= '1';
    tb_gt_rxresetdone <= '1';
    tb_gt_rxcdrlock <= '1';
    tb_gt_rxbyteisaligned <= '1';
    tb_gt_rxbyterealign <= '0';
    tb_gt_rxcommadet <= '0';
    tb_gt_txfault <= '0';
    tb_gt_rxlos <= '0';
    tb_gt_modabs <= '0';

    -----------
    -- CLOCK --
    -----------
    tb_clk <= not tb_clk after 5 ns;

    ------------------
    -- MAIN PROCESS --
    ------------------
    p_main:process

        variable iline : line;
        variable iword : std_logic_vector(31 downto 0);

    begin

        -- Wait and assert reset
        for I in 0 to 10 loop
            wait until rising_edge(tb_clk);
        end loop;
        tb_rstn <= '0';
        tb_gt_datarx <= (others => '1');

        -- Wait and deassert reset
        for I in 0 to 10 loop
            wait until rising_edge(tb_clk);
        end loop;
        tb_rstn <= '1';

        -- Wait for GT reset deassert
        wait until rising_edge(tb_clk) and tb_gt_rstall = '0';

        -- Read file
        while not endfile(file_input) loop

            wait until rising_edge(tb_clk);

            readline(file_input, iline);
            hread(iline, iword);

            wait until falling_edge(tb_clk);
            tb_gt_datarx <= iword(15 downto 0);

        end loop;

        -- End of test
        test_done <= True;

    end process;

    --------------------
    -- AXI CONNEXIONS --
    --------------------
    tb_s_axi_clk <= '0';
    tb_s_axi_resetn <= '0';

    -----------------------
    -- DUT INSTANCIATION --
    -----------------------
    dut_inst: entity work.combpm_protocol_electron
    port map(
        gt_clk => tb_clk,
        rst_n => tb_rstn,
        gt_datarx => tb_gt_datarx,
        gt_datatx => tb_gt_datatx,
        gt_powergood => tb_gt_powergood,
        gt_qplllock => tb_gt_qplllock,
        gt_txclkactive => tb_gt_txclkactive,
        gt_rxclkactive => tb_gt_rxclkactive,
        gt_txresetdone => tb_gt_txresetdone,
        gt_rxresetdone => tb_gt_rxresetdone,
        gt_rxcdrlock => tb_gt_rxcdrlock,
        gt_rxbyteisaligned => tb_gt_rxbyteisaligned,
        gt_rxbyterealign => tb_gt_rxbyterealign,
        gt_rxcommadet => tb_gt_rxcommadet,
        gt_txfault => tb_gt_txfault,
        gt_rxlos => tb_gt_rxlos,
        gt_modabs => tb_gt_modabs,
        gt_rstall => tb_gt_rstall,
        gt_rxcommadeten => tb_gt_rxcommadeten,
        gt_txdisable => tb_gt_txdisable,
        m_axi_tid => tb_m_axi_tid,
        m_axi_tdest => tb_m_axi_tdest,
        m_axi_tdata => tb_m_axi_tdata,
        m_axi_tstrb => tb_m_axi_tstrb,
        m_axi_tkeep => tb_m_axi_tkeep,
        m_axi_tlast => tb_m_axi_tlast,
        m_axi_tuser => tb_m_axi_tuser,
        m_axi_tvalid => tb_m_axi_tvalid,
        m_axi_tready => tb_m_axi_tready,
        S_AXI_CLK     => tb_s_axi_clk,
        S_AXI_RESETN  => tb_s_axi_resetn,
        S_AXI_AWADDR  => tb_s_axi_awaddr,
        S_AXI_AWPROT  => tb_s_axi_awprot,
        S_AXI_AWVALID => tb_s_axi_awvalid,
        S_AXI_AWREADY => tb_s_axi_awready,
        S_AXI_WDATA   => tb_s_axi_wdata,
        S_AXI_WSTRB   => tb_s_axi_wstrb,
        S_AXI_WVALID  => tb_s_axi_wvalid,
        S_AXI_WREADY  => tb_s_axi_wready,
        S_AXI_BRESP   => tb_s_axi_bresp,
        S_AXI_BVALID  => tb_s_axi_bvalid,
        S_AXI_BREADY  => tb_s_axi_bready,
        S_AXI_ARADDR  => tb_s_axi_araddr,
        S_AXI_ARPROT  => tb_s_axi_arprot,
        S_AXI_ARVALID => tb_s_axi_arvalid,
        S_AXI_ARREADY => tb_s_axi_arready,
        S_AXI_RDATA   => tb_s_axi_rdata,
        S_AXI_RRESP   => tb_s_axi_rresp,
        S_AXI_RVALID  => tb_s_axi_rvalid,
        S_AXI_RREADY  => tb_s_axi_rready

    );

end architecture testbench;