-- Testbench created online at:
--   www.doulos.com/knowhow/perl/testbench_creation/
-- Copyright Doulos Ltd
-- SD, 03 November 2002

library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;

entity top_tb is
  generic (
    g_NUM_DUTS : positive := 4;
    g_NUM_TRIG_INPUTS : positive := 6
    );
end;

architecture bench of top_tb is

  component top
      generic(
      constant FW_VERSION : unsigned(31 downto 0):= X"1e000022";
      g_NUM_DUTS  : positive := 4;
      g_NUM_TRIG_INPUTS   :positive := 6;
      g_NUM_EDGE_INPUTS   :positive := 6;
      g_NUM_EXT_SLAVES    :positive :=8;
      g_EVENT_DATA_WIDTH  :positive := 64;
      g_IPBUS_WIDTH   :positive := 32;
      g_SPILL_COUNTER_WIDTH   :positive := 12;
      g_BUILD_SIMULATED_MAC   :integer := 0
      );
      port(
          sysclk: in std_logic;
          sysclk_50_o_p : out std_logic;
          sysclk_50_o_n : out std_logic;
          sysclk_40_i_p: in std_logic;
          sysclk_40_i_n: in std_logic;
          leds: out std_logic_vector(3 downto 0);
          gpio: out std_logic;
          rgmii_txd: out std_logic_vector(3 downto 0);
          rgmii_tx_ctl: out std_logic;
          rgmii_txc: out std_logic;
          rgmii_rxd: in std_logic_vector(3 downto 0);
          rgmii_rx_ctl: in std_logic;
          rgmii_rxc: in std_logic;
          phy_rstn: out std_logic;
          i2c_scl_b: inout std_logic;
          i2c_sda_b: inout std_logic;
          i2c_reset: out std_logic;
          clk_gen_rst: out std_logic;
          busy_i: in std_logic_vector(g_NUM_DUTS-1 downto 0);
          busy_o: out std_logic_vector(g_NUM_DUTS-1 downto 0);
          cont_i: in std_logic_vector(g_NUM_DUTS-1 downto 0);
          cont_o: out std_logic_vector(g_NUM_DUTS-1 downto 0);
          spare_i: in std_logic_vector(g_NUM_DUTS-1 downto 0);
          spare_o: out std_logic_vector(g_NUM_DUTS-1 downto 0);
          triggers_i: in std_logic_vector(g_NUM_DUTS-1 downto 0);
          triggers_o: out std_logic_vector(g_NUM_DUTS-1 downto 0);
          dut_clk_i: in std_logic_vector(g_NUM_DUTS-1 downto 0);
          dut_clk_o: out std_logic_vector(g_NUM_DUTS-1 downto 0);
          threshold_discr_n_i: in std_logic_vector(g_NUM_TRIG_INPUTS-1 downto 0);
          threshold_discr_p_i: in std_logic_vector(g_NUM_TRIG_INPUTS-1 downto 0)
      );
  end component;

  signal sysclk , sysclk_50 , sysclk_40: std_logic;
  signal sysclk_50_o_p: std_logic;
  signal sysclk_50_o_n: std_logic;
  signal sysclk_40_i_p: std_logic;
  signal sysclk_40_i_n: std_logic;
  signal leds: std_logic_vector(3 downto 0);
  signal gpio: std_logic;
  signal rgmii_txd: std_logic_vector(3 downto 0);
  signal rgmii_tx_ctl: std_logic;
  signal rgmii_txc: std_logic;
  signal rgmii_rxd: std_logic_vector(3 downto 0);
  signal rgmii_rx_ctl: std_logic;
  signal rgmii_rxc: std_logic;
  signal phy_rstn: std_logic ;
  signal i2c_scl_b: std_logic;
  signal i2c_sda_b: std_logic;
  signal i2c_reset: std_logic;
  signal clk_gen_rst: std_logic;
  signal busy_i: std_logic_vector(g_NUM_DUTS-1 downto 0):= (others => '0');
  signal busy_o: std_logic_vector(g_NUM_DUTS-1 downto 0);
  signal cont_i: std_logic_vector(g_NUM_DUTS-1 downto 0):= (others => '0');
  signal cont_o: std_logic_vector(g_NUM_DUTS-1 downto 0);
  signal spare_i: std_logic_vector(g_NUM_DUTS-1 downto 0):= (others => '0');
  signal spare_o: std_logic_vector(g_NUM_DUTS-1 downto 0);
  signal triggers_i: std_logic_vector(g_NUM_DUTS-1 downto 0):= (others => '0');
  signal triggers_o: std_logic_vector(g_NUM_DUTS-1 downto 0);
  signal dut_clk_i: std_logic_vector(g_NUM_DUTS-1 downto 0):= (others => '0');
  signal dut_clk_o: std_logic_vector(g_NUM_DUTS-1 downto 0);
  signal threshold_discr_n_i: std_logic_vector(g_NUM_TRIG_INPUTS-1 downto 0) := (others => '1');
  signal threshold_discr_p_i: std_logic_vector(g_NUM_TRIG_INPUTS-1 downto 0) := (others => '0');

  -- Simulate mis-match between nominal 50MHz clock freq and actual freq
  constant freqDrift: time := 0.01 ns;
  
  constant sysclk_period: time := 20 ns + freqDrift;
  constant sysclk_40_period: time := 25 ns;
  
  signal stop_the_clock: boolean;

begin

  -- Insert values for generic parameters !!
  uut: top generic map (
                         g_BUILD_SIMULATED_MAC => 1 )
              port map ( sysclk                => sysclk,
                         sysclk_50_o_p         => sysclk_50_o_p,
                         sysclk_50_o_n         => sysclk_50_o_n,
                         sysclk_40_i_p         => sysclk_40_i_p,
                         sysclk_40_i_n         => sysclk_40_i_n,
                         leds                  => leds,
                         gpio                  => gpio,
                         rgmii_txd             => rgmii_txd,
                         rgmii_tx_ctl          => rgmii_tx_ctl,
                         rgmii_txc             => rgmii_txc,
                         rgmii_rxd             => rgmii_rxd,
                         rgmii_rx_ctl          => rgmii_rx_ctl,
                         rgmii_rxc             => rgmii_rxc,
                         phy_rstn              => phy_rstn,
                         i2c_scl_b             => i2c_scl_b,
                         i2c_sda_b             => i2c_sda_b,
                         i2c_reset             => i2c_reset,
                         clk_gen_rst           => clk_gen_rst,
                         busy_i                => busy_i,
                         busy_o                => busy_o,
                         cont_i                => cont_i,
                         cont_o                => cont_o,
                         spare_i               => spare_i,
                         spare_o               => spare_o,
                         triggers_i            => triggers_i,
                         triggers_o            => triggers_o,
                         dut_clk_i             => dut_clk_i,
                         dut_clk_o             => dut_clk_o,
                         threshold_discr_n_i   => threshold_discr_n_i,
                         threshold_discr_p_i   => threshold_discr_p_i );

  stimulus: process
  begin
  
    -- Put initialisation code here


    -- Put test bench stimulus code here
    wait;
    
    stop_the_clock <= true;
    wait;
  end process;

  sysclk_clock: process
  begin
    while not stop_the_clock loop
      sysclk <= '0', '1' after sysclk_period / 2;
      wait for sysclk_period;
    end loop;
    wait;
  end process;

  sysclk_40_clock: process
  begin
    while not stop_the_clock loop
      sysclk_40 <= '0', '1' after sysclk_40_period / 2;
      wait for sysclk_40_period;
    end loop;
    wait;
  end process;
  sysclk_40_i_p <= sysclk_40;
  sysclk_40_i_n <= not sysclk_40;

end;
  
