-- ======================================================
--   Complete functional simulation for Example 1
-- ======================================================
--
--  Module      : TB_EXAMPLE1
--  Date        : 14/05/2007
--  Author      : R. Williams - HUNT ENGINEERING
--
-- ==============================================================
--
--  Ver     Modified By      Date      Changes
--  ---     -----------      ----      -------
--  1.0     R. Williams    01-07-04    First Written
--  1.1     R. Williams    14-05-07    Corrected mistakes in file
--
-- ==============================================================


library IEEE;
  use IEEE.std_logic_1164.all;

library sim_lib;
  use sim_lib.all;


entity TESTBENCH is
end TESTBENCH;

architecture BENCH of TESTBENCH is

  component TOP
    port (
      -- PADS - HE_WCLK
      doclk         : in  std_logic;
      f0            : out std_logic;
      -- PADS - HE_WR_6F
      dof_ff        : in  std_logic_vector(5 downto 0);
      dof_af        : in  std_logic_vector(5 downto 0);
      dof_wen       : out std_logic_vector(5 downto 0);
      do            : out std_logic_vector(31 downto 0);
      -- PADS - HE_RCLK
      diclk         : in  std_logic;
      f1            : out std_logic;
      -- PADS - HE_RD_6F
      dif_ef        : in  std_logic_vector(5 downto 0);
      dif_ae        : in  std_logic_vector(5 downto 0);
      dif_ren       : out std_logic_vector(5 downto 0);
      dif_oen       : out std_logic_vector(5 downto 0);
      di            : in  std_logic_vector(31 downto 0);
      -- PADS - HE_DDR
      sdram_clkin   : in  std_logic;
      sdram_a_clk_p : out std_logic;
      sdram_a_clk_n : out std_logic;
      sdram_a_a     : out std_logic_vector(13 downto 0);
      sdram_a_ba    : out std_logic_vector(1 downto 0);
      sdram_a_dq    : inout std_logic_vector(31 downto 0):= (OTHERS => 'Z');
      sdram_a_dqs   : inout std_logic_vector(3 downto 0):= (OTHERS => 'Z');
      sdram_a_dm    : out std_logic_vector(3 downto 0);
      sdram_a_ras   : out std_logic;
      sdram_a_cas   : out std_logic;
      sdram_a_we    : out std_logic;
      -- PADS - HSB
      adstrb        : in  std_logic;
      ad            : in  std_logic;
      rdwr          : in  std_logic;
      done          : out std_logic;
      ad_bus        : inout std_logic_vector(3 downto 0);
      mff           : in  std_logic;
      mack          : in  std_logic;
      mclk          : out std_logic;
      mdat          : out std_logic;
      -- PADS - Connector Digital I/O
      dio_a         : inout std_logic_vector(29 downto 0);
      dio_b         : inout std_logic_vector(29 downto 0);
      dio_c         : inout std_logic_vector(29 downto 0);
      dio_d         : inout std_logic_vector(29 downto 0);
      dio_e         : inout std_logic_vector(29 downto 0);
      dio_f         : inout std_logic_vector(29 downto 0);
      -- CONTROL signals
      config        : in  std_logic;
      reset_pin     : in  std_logic;
      udpres        : out std_logic;
      -- OSC/CLOCKS
      osc0_pin      : in  std_logic;
      osc3_pin      : in  std_logic;
      -- MISC I/O
      led             : out std_logic_vector(4 downto 0);
      cid             : in std_logic_vector(3 downto 0);
      mid             : in std_logic_vector(3 downto 0);
      umi             : inout std_logic_vector(3 downto 0);
      module_has_proc : out std_logic
    );
  end component;

  component SIM_RD_6F
    generic (
      FILE_IN0 : string;
      FILE_IN1 : string;
      FILE_IN2 : string;
      FILE_IN3 : string;
      FILE_IN4 : string;
      FILE_IN5 : string
    );
    port (
      GO      : in  boolean;                       -- start module activity
      CLK     : in  std_logic;                     -- FIFO clock
      DIF_REN : in  std_logic_vector(5 downto 0);  -- read enables
      DIF_OEN : in  std_logic_vector(5 downto 0);  -- output enable
      ENDF0   : out boolean;                       -- end of file 0
      ENDF1   : out boolean;                       -- end of file 1
      ENDF2   : out boolean;                       -- end of file 2
      ENDF3   : out boolean;                       -- end of file 3
      ENDF4   : out boolean;                       -- end of file 4
      ENDF5   : out boolean;                       -- end of file 5
      DIF_EF  : out std_logic_vector(5 downto 0);  -- empty flags
      DIF_AE  : out std_logic_vector(5 downto 0);  -- almost empty flags
      DI      : out std_logic_vector(31 downto 0)  -- read data
    );
  end component;

  component SIM_WR_6F
    generic (
      FILE_OUT0 : string;
      FILE_OUT1 : string;
      FILE_OUT2 : string;
      FILE_OUT3 : string;
      FILE_OUT4 : string;
      FILE_OUT5 : string
    );
    port (
      CLK     : in  std_logic;                      -- FIFO clock
      DOF_WEN : in  std_logic_vector(5 downto 0);   -- write enables
      DO      : in  std_logic_vector(31 downto 0);  -- write data
      DOF_FF  : out std_logic_vector(5 downto 0);   -- full flags
      DOF_AF  : out std_logic_vector(5 downto 0)    -- almost full flags
    );
  end component;

  component SIM_MSG
    port (
      ADSTRB : out std_logic;
      AD     : out std_logic;
      RDWR   : out std_logic;
      DONE   : in  std_logic;
      AD_BUS : inout std_logic_vector(3 downto 0);
      MFF    : out std_logic;
      MACK   : out std_logic;
      MCLK   : in  std_logic;
      MDAT   : out std_logic;
      --
      START  : in  boolean;                         -- transaction -> start operation
      OP     : in  std_logic;                       -- 1/read - 0/write
      ADDR   : in  std_logic_vector(7 downto 0);    -- address
      DIN    : in  std_logic_vector(7 downto 0);    -- write data
      DOUT   : out std_logic_vector(7 downto 0);    -- read data
      READY  : out boolean                          -- 0/busy - 1/finished
    );
  end component;

  -- TOP I/Os
  signal DOCLK           : std_logic;
  signal F0              : std_logic;
  signal DOF_FF          : std_logic_vector(5 downto 0);
  signal DOF_AF          : std_logic_vector(5 downto 0);
  signal DOF_WEN         : std_logic_vector(5 downto 0);
  signal DO              : std_logic_vector(31 downto 0);
  signal DICLK           : std_logic;
  signal F1              : std_logic;
  signal DIF_EF          : std_logic_vector(5 downto 0);
  signal DIF_AE          : std_logic_vector(5 downto 0);
  signal DIF_REN         : std_logic_vector(5 downto 0);
  signal DIF_OEN         : std_logic_vector(5 downto 0);
  signal DI              : std_logic_vector(31 downto 0);
  signal SDRAM_CLKIN     : std_logic := '0';
  signal SDRAM_A_CLK_P   : std_logic;
  signal SDRAM_A_CLK_N   : std_logic;
  signal SDRAM_A_A       : std_logic_vector(13 downto 0);
  signal SDRAM_A_BA      : std_logic_vector(1 downto 0);
  signal SDRAM_A_DQ      : std_logic_vector(31 downto 0);
  signal SDRAM_A_DQS     : std_logic_vector(3 downto 0);
  signal SDRAM_A_DM      : std_logic_vector(3 downto 0);
  signal SDRAM_A_RAS     : std_logic;
  signal SDRAM_A_CAS     : std_logic;
  signal SDRAM_A_WE      : std_logic;
  signal ADSTRB          : std_logic;
  signal AD              : std_logic;
  signal RDWR            : std_logic;
  signal DONE            : std_logic;
  signal AD_BUS          : std_logic_vector(3 downto 0);
  signal MFF             : std_logic;
  signal MACK            : std_logic;
  signal MCLK            : std_logic;
  signal MDAT            : std_logic;
  signal DIO_A           : std_logic_vector(29 downto 0);
  signal DIO_B           : std_logic_vector(29 downto 0);
  signal DIO_C           : std_logic_vector(29 downto 0);
  signal DIO_D           : std_logic_vector(29 downto 0);
  signal DIO_E           : std_logic_vector(29 downto 0);
  signal DIO_F           : std_logic_vector(29 downto 0);
  signal CONFIG          : std_logic;
  signal RESET_PIN       : std_logic;
  signal UDPRES          : std_logic;
  signal OSC0_PIN        : std_logic;
  signal OSC3_PIN        : std_logic := '0';
  signal LED             : std_logic_vector(4 downto 0);
  signal CID             : std_logic_vector(3 downto 0);
  signal MID             : std_logic_vector(3 downto 0);
  signal UMI             : std_logic_vector(3 downto 0);
  signal MODULE_HAS_PROC : std_logic;

  -- oscillator period
  constant period     : time := 10 ns;
  -- DDR SDRAM clock period
  constant ddr_period : time := 5 ns;
  -- input FIFO ID
  constant FIFO_IN  : std_logic_vector(5 downto 0) := "000001";
  -- output FIFO ID
  constant FIFO_OUT : std_logic_vector(5 downto 0) := "000010";

  signal GO        : boolean;
  signal ENDF0     : boolean;
  signal ENDF1     : boolean;
  signal ENDF2     : boolean;
  signal ENDF3     : boolean;
  signal ENDF4     : boolean;
  signal ENDF5     : boolean;
  signal MSG_START : boolean;
  signal MSG_OP    : std_logic := '1';
  signal MSG_ADDR  : std_logic_vector(7 downto 0);
  signal MSG_DIN   : std_logic_vector(7 downto 0);
  signal MSG_DOUT  : std_logic_vector(7 downto 0);
  signal MSG_READY : boolean;

begin

  OSC3_PIN <= NOT OSC3_PIN after (period/2);

-- ----------------------------------------
--  FPGA
-- ----------------------------------------

  UUT: TOP
    port map (
      -- PADS - HE_WCLK
      doclk           => DOCLK,
      f0              => F0,
      -- PADS - HE_WR_6F
      dof_ff          => DOF_FF,
      dof_af          => DOF_AF,
      dof_wen         => DOF_WEN,
      do              => DO,
      -- PADS - HE_RCLK
      diclk           => DICLK,
      f1              => F1,
      -- PADS - HE_RD_6F
      dif_ef          => DIF_EF,
      dif_ae          => DIF_AE,
      dif_ren         => DIF_REN,
      dif_oen         => DIF_OEN,
      di              => DI,
      -- PADS - HE_DDR
      sdram_clkin     => SDRAM_CLKIN,
      sdram_a_clk_p   => SDRAM_A_CLK_P,
      sdram_a_clk_n   => SDRAM_A_CLK_N,
      sdram_a_a       => SDRAM_A_A,
      sdram_a_ba      => SDRAM_A_BA,
      sdram_a_dq      => SDRAM_A_DQ,
      sdram_a_dqs     => SDRAM_A_DQS,
      sdram_a_dm      => SDRAM_A_DM,
      sdram_a_ras     => SDRAM_A_RAS,
      sdram_a_cas     => SDRAM_A_CAS,
      sdram_a_we      => SDRAM_A_WE,
      -- PADS - HSB
      adstrb          => ADSTRB,
      ad              => AD,
      rdwr            => RDWR,
      done            => DONE,
      ad_bus          => AD_BUS,
      mff             => MFF,
      mack            => MACK,
      mclk            => MCLK,
      mdat            => MDAT,
      -- PADS - Connector Digital I/O
      dio_a           => DIO_A,
      dio_b           => DIO_B,
      dio_c           => DIO_C,
      dio_d           => DIO_D,
      dio_e           => DIO_E,
      dio_f           => DIO_F,
      -- CONTROL signals
      config          => CONFIG,
      reset_pin       => RESET_PIN,
      udpres          => UDPRES,
      -- OSC/CLOCKS
      osc0_pin        => OSC0_PIN,
      osc3_pin        => OSC3_PIN,
      -- MISC I/O
      led             => LED,
      cid             => CID,
      mid             => MID,
      umi             => UMI,
      module_has_proc => MODULE_HAS_PROC );

-- ----------------------------------------
--  OUTPUT FIFO
-- ----------------------------------------
-- TOP outputs : F0, DOF_WEN, DO
-- TOP inputs  : DOCLK, DOF_FF, DOF_AF

  DOCLK <= F0;

  iWR6F : SIM_WR_6F
    generic map(
      FILE_OUT0 => "..\Sim\Fifo_Out0.TXT",
      FILE_OUT1 => "..\Sim\Fifo_Out1.TXT",
      FILE_OUT2 => "..\Sim\Fifo_Out2.TXT",
      FILE_OUT3 => "..\Sim\Fifo_Out3.TXT",
      FILE_OUT4 => "..\Sim\Fifo_Out4.TXT",
      FILE_OUT5 => "..\Sim\Fifo_Out5.TXT" )
    port map (
      CLK     => F0,
      DOF_WEN => DOF_WEN,
      DO      => DO,
      DOF_FF  => DOF_FF,
      DOF_AF  => DOF_AF );

-- ----------------------------------------
--  INPUT FIFO
-- ----------------------------------------
-- TOP outputs : F1, DIF_REN, DIF_OEN
-- TOP inputs  : DICLK, DIF_EF, DIF_AE, DI

  DICLK <= F1;

  iRD6F : SIM_RD_6F
    generic map (
      FILE_IN0 => "..\Sim\Fifo_In0.TXT",
      FILE_IN1 => "..\Sim\Fifo_In1.TXT",
      FILE_IN2 => "..\Sim\Fifo_In2.TXT",
      FILE_IN3 => "..\Sim\Fifo_In3.TXT",
      FILE_IN4 => "..\Sim\Fifo_In4.TXT",
      FILE_IN5 => "..\Sim\Fifo_In5.TXT" )
    port map (
      GO      => GO,
      CLK     => F1,
      DIF_REN => DIF_REN,
      DIF_OEN => DIF_OEN,
      ENDF0   => ENDF0,
      ENDF1   => ENDF1,
      ENDF2   => ENDF2,
      ENDF3   => ENDF3,
      ENDF4   => ENDF4,
      ENDF5   => ENDF5,
      DIF_EF  => DIF_EF,
      DIF_AE  => DIF_AE,
      DI      => DI );

-- ----------------------------------------
--  DDR SDRAM INTERFACE
-- ----------------------------------------
-- TOP outputs : SDRAM_A_CLK_P, SDRAM_A_CLK_N, SDRAM_A_A, SDRAM_A_BA,
--             : SDRAM_A_DM, SDRAM_A_RAS, SDRAM_A_CAS, SDRAM_A_WE
-- TOP inputs  : SDRAM_CLKIN
-- TOP inouts  : SDRAM_A_DQ, SDRAM_A_DQS

  SDRAM_CLKIN <= NOT SDRAM_CLKIN after (ddr_period/2);

  SDRAM_A_DQ  <= (others=>'Z');
  SDRAM_A_DQS <= (others=>'Z');

-- ----------------------------------------
--  HSB MESSAGE INTERFACE
-- ----------------------------------------
-- TOP outputs : DONE, MCLK, MDAT
-- TOP inputs  : ADSTRB, AD, RDWR, MFF, MACK
-- TOP inouts  : AD_BUS

  iMSG : SIM_MSG
    port map (
      ADSTRB => ADSTRB,
      AD     => AD,
      RDWR   => RDWR,
      DONE   => DONE,
      AD_BUS => AD_BUS,
      MFF    => MFF,
      MACK   => MACK,
      MCLK   => MCLK,
      MDAT   => MDAT,
      --
      START  => MSG_START,
      OP     => MSG_OP,
      ADDR   => MSG_ADDR,
      DIN    => MSG_DIN,
      DOUT   => MSG_DOUT,
      READY  => MSG_READY );

-- ----------------------------------------
--  Connector Digital IO
-- ----------------------------------------
-- TOP inouts  : DIO_A, DIO_B, DIO_C, DIO_D,
--             : DIO_E, DIO_F

  DIO_A <= (others=>'0');
  DIO_B <= (others=>'0');
  DIO_C <= (others=>'0');
  DIO_D <= (others=>'0');
  DIO_E <= (others=>'0');
  DIO_F <= (others=>'0');

-- ----------------------------------------
--  STIMULI
-- ----------------------------------------

  process
  begin
    GO <= false;

    RESET_PIN <= '0';
    wait for (period*5);
    RESET_PIN <= '1';
    wait for (period*20);

    -- configure input FIFO number
    MSG_OP   <= '0';
    MSG_ADDR <= X"00";
    MSG_DIN  <= "00" & FIFO_IN;
    MSG_START <= true;
    wait until MSG_READY;
    -- configure output FIFO number
    MSG_OP   <= '0';
    MSG_ADDR <= X"01";
    MSG_DIN  <= "00" & FIFO_OUT;
    MSG_START <= true;
    wait until MSG_READY;

    -- read back input FIFO number
    MSG_OP   <= '1';
    MSG_ADDR <= X"00";
    MSG_START <= true;
    wait until MSG_READY;
    -- read back output FIFO number
    MSG_OP   <= '1';
    MSG_ADDR <= X"01";
    MSG_START <= true;
    wait until MSG_READY;

    -- SW reset
    wait for (period*20);
    RESET_PIN <= '0';
    wait for (period*5);
    RESET_PIN <= '1';
    wait for (period*20);

    -- launch FIFO read
    GO <= true;

    -- end of simulation
    wait until ENDF0;
    wait until ENDF1;
    wait until ENDF2;
    wait until ENDF3;
    wait until ENDF4;
    wait until ENDF5;

    wait for (period*500);
    assert false report "End of simulation" severity failure;
  end process;

end BENCH;
