--*****************************************************************************
-- (c) Copyright 2009 - 2010 Xilinx, Inc. All rights reserved.
--
-- This file contains confidential and proprietary information
-- of Xilinx, Inc. and is protected under U.S. and
-- international copyright and other intellectual property
-- laws.
--
-- DISCLAIMER
-- This disclaimer is not a license and does not grant any
-- rights to the materials distributed herewith. Except as
-- otherwise provided in a valid license issued to you by
-- Xilinx, and to the maximum extent permitted by applicable
-- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
-- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
-- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
-- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
-- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
-- (2) Xilinx shall not be liable (whether in contract or tort,
-- including negligence, or under any other theory of
-- liability) for any loss or damage of any kind or nature
-- related to, arising under or in connection with these
-- materials, including for any direct, or any indirect,
-- special, incidental, or consequential loss or damage
-- (including loss of data, profits, goodwill, or any type of
-- loss or damage suffered as a result of any action brought
-- by a third party) even if such damage or loss was
-- reasonably foreseeable or Xilinx had been advised of the
-- possibility of the same.
--
-- CRITICAL APPLICATIONS
-- Xilinx products are not designed or intended to be fail-
-- safe, or for use in any application requiring fail-safe
-- performance, such as life-support or safety devices or
-- systems, Class III medical devices, nuclear facilities,
-- applications related to the deployment of airbags, or any
-- other applications that could lead to death, personal
-- injury, or severe property or environmental damage
-- (individually and collectively, "Critical
-- Applications"). Customer assumes the sole risk and
-- liability of any use of Xilinx products in Critical
-- Applications, subject only to applicable laws and
-- regulations governing limitations on product liability.
--
-- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
-- PART OF THIS FILE AT ALL TIMES.
--
--*****************************************************************************
--   ____  ____
--  /   /\/   /
-- /___/  \  /    Vendor             : Xilinx
-- \   \   \/     Version            : 3.92
--  \   \         Application        : MIG
--  /   /         Filename           : sim_tb_top.vhd
-- /___/   /\     Date Last Modified : $Date: 2011/06/02 07:17:34 $
-- \   \  /  \    Date Created       : Mon Jun 23 2008
--  \___\/\___\
--
-- Device           : Virtex-6
-- Design Name      : DDR3 SDRAM
-- Purpose          :
--                   Top-level testbench for testing DDR3.
--                   Instantiates:
--                     1. IP_TOP (top-level representing FPGA, contains core,
--                        clocking, built-in testbench/memory checker and other
--                        support structures)
--                     2. DDR3 Memory
--                     3. Miscellaneous clock generation and reset logic
--                     4. For ECC ON case inserts error on LSB bit
--                        of data from DRAM to FPGA.
-- Reference        :
-- Revision History :
--*****************************************************************************

library ieee;
library unisim;
use ieee.std_logic_1164.all;
use unisim.vcomponents.all;
use ieee.numeric_std.all;

entity sim_tb_top is
end entity sim_tb_top;

architecture arch_sim_tb_top of sim_tb_top is

  constant REFCLK_FREQ           : real := 200.0;
                                    -- # = 200 for all design frequencies of
                                    --         -1 speed grade devices
                                    --   = 200 when design frequency < 480 MHz
                                    --         for -2 and -3 speed grade devices.
                                    --   = 300 when design frequency >= 480 MHz
                                    --         for -2 and -3 speed grade devices.
  constant SIM_BYPASS_INIT_CAL   : string := "FAST";
                                    -- # = "OFF" -  Complete memory init &
                                    --              calibration sequence
                                    -- # = "SKIP" - Skip memory init &
                                    --              calibration sequence
                                    -- # = "FAST" - Skip memory init & use
                                    --              abbreviated calib sequence
  constant RST_ACT_LOW           : integer := 1;
                                    -- =1 for active low reset,
                                    -- =0 for active high.
  constant IODELAY_GRP           : string := "IODELAY_MIG";
                                    --to phy_top
  constant nCK_PER_CLK           : integer := 2;
                                    -- # of memory CKs per fabric clock.
                                    -- # = 2, 1.
  constant nCS_PER_RANK          : integer := 1;
                                    -- # of unique CS outputs per Rank for
                                    -- phy.
  constant DQS_CNT_WIDTH         : integer := 3;
                                    -- # = ceil(log2(DQS_WIDTH)).
  constant RANK_WIDTH            : integer := 1;
                                    -- # = ceil(log2(RANKS)).
  constant BANK_WIDTH            : integer := 3;
                                    -- # of memory Bank Address bits.
  constant CK_WIDTH              : integer := 1;
                                    -- # of CK/CK# outputs to memory.
  constant CKE_WIDTH             : integer := 1;
                                    -- # of CKE outputs to memory.
  constant COL_WIDTH             : integer := 10;
                                    -- # of memory Column Address bits.
  constant CS_WIDTH              : integer := 1;
                                    -- # of unique CS outputs to memory.
  constant DM_WIDTH              : integer := 8;
                                    -- # of Data Mask bits.
  constant DQ_WIDTH              : integer := 64;
                                    -- # of Data (DQ) bits.
  constant DQS_WIDTH             : integer := 8;
                                    -- # of DQS/DQS# bits.
  constant ROW_WIDTH             : integer := 15;
                                    -- # of memory Row Address bits.
  constant BURST_MODE            : string := "8";
                                    -- Burst Length (Mode Register 0).
                                    -- # = "8", "4", "OTF".
  constant INPUT_CLK_TYPE        : string := "SINGLE_ENDED";
                                    -- input clock type DIFFERENTIAL or SINGLE_ENDED
  constant BM_CNT_WIDTH          : integer := 2;
                                    -- # = ceil(log2(nBANK_MACHS)).
  constant ADDR_CMD_MODE         : string  := "1T" ;
                                    -- # = "2T", "1T".
  constant ORDERING              : string := "STRICT";
                                    -- # = "NORM", "STRICT".
  constant RTT_NOM               : string := "60";
                                    -- RTT_NOM (ODT) (Mode Register 1).
                                    -- # = "DISABLED" - RTT_NOM disabled,
                                    --   = "120" - RZQ/2,
                                    --   = "60" - RZQ/4,
                                    --   = "40" - RZQ/6.
  constant RTT_WR                : string := "OFF";
                                       -- RTT_WR (ODT) (Mode Register 2).
                                       -- # = "OFF" - Dynamic ODT off,
                                       --   = "120" - RZQ/2,
                                       --   = "60" - RZQ/4,
  constant OUTPUT_DRV            : string := "HIGH";
                                    -- Output Driver Impedance Control (Mode Register 1).
                                    -- # = "HIGH" - RZQ/7,
                                    --   = "LOW" - RZQ/6.
  constant REG_CTRL              : string := "OFF";
                                    -- # = "ON" - RDIMMs,
                                    --   = "OFF" - Components, SODIMMs, UDIMMs.
  constant CLKFBOUT_MULT_F       : integer := 6;
                                    -- write PLL VCO multiplier.
  constant DIVCLK_DIVIDE         : integer := 2;
                                    -- write PLL VCO divisor.
  constant CLKOUT_DIVIDE         : integer := 3;
                                    -- VCO output divisor for fast (memory) clocks.
  constant tCK                   : integer := 2500;
                                    -- memory tCK paramter.
                                    -- # = Clock Period.
  constant DEBUG_PORT            : string := "OFF";
                                    -- # = "ON" Enable debug signals/controls.
                                    --   = "OFF" Disable debug signals/controls.
  constant tPRDI                 : integer := 1000000;
                                    -- memory tPRDI paramter.
  constant tREFI                 : integer := 7800000;
                                    -- memory tREFI paramter.
  constant tZQI                  : integer := 128000000;
                                    -- memory tZQI paramter.
  constant ADDR_WIDTH            : integer := 29;
                                    -- # = RANK_WIDTH + BANK_WIDTH
                                    --     + ROW_WIDTH + COL_WIDTH;
  constant STARVE_LIMIT          : integer := 2;
                                    -- # = 2,3,4.
  constant TCQ                   : integer := 100;
  constant ECC                   : string := "OFF";
  constant ECC_TEST              : string := "OFF";
  constant DATA_WIDTH : integer := 64;
  constant PAYLOAD_WIDTH : integer := 64;

  --***********************************************************************--
  -- Traffic Gen related parameters
  --***********************************************************************--
  constant EYE_TEST              : string := "FALSE";
                                    -- set EYE_TEST = "TRUE" to probe memory
                                    -- signals. Traffic Generator will only
                                    -- write to one single location and no
                                    -- read transactions will be generated.
  constant SIMULATION            : string := "TRUE";
  constant DATA_MODE             : std_logic_vector(3 downto 0) := "0010";
  constant ADDR_MODE             : std_logic_vector(2 downto 0) := "011";
  constant TST_MEM_INSTR_MODE    : string := "R_W_INSTR_MODE";
  constant DATA_PATTERN          : string := "DGEN_ALL";
                                     -- DATA_PATTERN shoule be set to "DGEN_ALL"
                                     -- unless it is targeted for S6 small device.
                                     -- "DGEN_HAMMER", "DGEN_WALKING1",
                                     -- "DGEN_WALKING0","DGEN_ADDR","
                                     -- "DGEN_NEIGHBOR","DGEN_PRBS","DGEN_ALL"
  constant CMD_PATTERN           : string := "CGEN_ALL";
                                     -- CMD_PATTERN shoule be set to "CGEN_ALL"
                                     -- unless it is targeted for S6 small device.
                                     -- "CGEN_RPBS","CGEN_FIXED","CGEN_BRAM",
                                     -- "CGEN_SEQUENTIAL", "CGEN_ALL"

  constant BEGIN_ADDRESS         : std_logic_vector(31 downto 0) := X"00000000";
  constant PRBS_SADDR_MASK_POS   : std_logic_vector(31 downto 0) := X"00000000";
  constant END_ADDRESS           : std_logic_vector(31 downto 0) := X"000003ff";
  constant PRBS_EADDR_MASK_POS   : std_logic_vector(31 downto 0) := X"fffffc00";
  constant SEL_VICTIM_LINE       : integer := 11;

  --**************************************************************************--
  -- Local constants Declarations
  --**************************************************************************--
  constant TPROP_DQS         : time := 0 ps;  -- Delay for DQS signal during Write Operation
  constant TPROP_DQS_RD      : time := 0 ps;  -- Delay for DQS signal during Read Operation
  constant TPROP_PCB_CTRL    : time := 0 ps;  -- Delay for Address and Ctrl signals
  constant TPROP_PCB_DATA    : time := 0 ps;  -- Delay for data signal during Write operation
  constant TPROP_PCB_DATA_RD : time := 0 ps;  -- Delay for data signal during Read operation

  constant MEMORY_WIDTH       : integer := 16;
  constant NUM_COMP           : integer := DQ_WIDTH/MEMORY_WIDTH;
  constant CLK_PERIOD         : time    := tCK * 1000 fs;
  constant REFCLK_HALF_PERIOD : time := (1000000.0/(2.0*REFCLK_FREQ)) * 1 ps;
  constant DRAM_DEVICE        : string  := "COMP";
                         -- DRAM_TYPE: "UDIMM", "RDIMM", "COMPS"

   -- VT delay change options/settings
  constant VT_ENABLE          : string := "OFF";
                                       -- Enable VT delay var's
  constant VT_RATE            : time   := time(CLK_PERIOD)/500;
                                       -- Size of each VT step
  constant VT_UPDATE_INTERVAL : time   := time(CLK_PERIOD)*50;
                                       -- Update interval
  constant VT_MAX             : time   := time(CLK_PERIOD)/40;
                                        -- Maximum VT shift


 function STR_TO_INT return integer is
  begin
   if(BURST_MODE = "8") then
     return 8;
   elsif(BURST_MODE = "4") then
     return 4;
   else
     return 0;
   end if;
  end function;

  constant APP_DATA_WIDTH : integer := PAYLOAD_WIDTH * 4;
  constant APP_MASK_WIDTH : integer := APP_DATA_WIDTH/8;
  constant BURST_LENGTH   : integer := STR_TO_INT;

  component WireDelay
    generic (
       Delay_g    : time;
       Delay_rd   : time;
       ERR_INSERT : string);
    port
      (A             : inout Std_Logic;
       B             : inout Std_Logic;
       reset         : in    Std_Logic;
       phy_init_done : in    Std_Logic
       );
  end component WireDelay;

  component ddr3_ram
    generic(
      nCK_PER_CLK        : integer;
      tCK                : integer;
      RST_ACT_LOW        : integer;
      REFCLK_FREQ        : real;
      IODELAY_GRP : string;
      INPUT_CLK_TYPE     : string;
      BANK_WIDTH         : integer;
      CK_WIDTH           : integer;
      CKE_WIDTH          : integer;
      COL_WIDTH          : integer;
      nCS_PER_RANK       : integer;
      DQ_WIDTH           : integer;
      DM_WIDTH           : integer;
      DQS_CNT_WIDTH      : integer;
      DQS_WIDTH          : integer;
      ROW_WIDTH          : integer;
      RANK_WIDTH         : integer;
      CS_WIDTH           : integer;
      BURST_MODE         : string;
      BM_CNT_WIDTH       : integer;
      CLKFBOUT_MULT_F    : integer;
      DIVCLK_DIVIDE      : integer;
      CLKOUT_DIVIDE      : integer;
      OUTPUT_DRV         : string;
      REG_CTRL           : string;
      RTT_NOM            : string;
      RTT_WR             : string;
      SIM_BYPASS_INIT_CAL: string;
      DEBUG_PORT         : string;
      ADDR_CMD_MODE      : string;
      ORDERING           : string;
      STARVE_LIMIT       : integer;
      tPRDI              : integer;
      tREFI              : integer;
      tZQI               : integer;
      ADDR_WIDTH         : integer;
      ECC                : string;
      ECC_TEST           : string;
      TCQ                 : integer;
      DATA_WIDTH          : integer;
      PAYLOAD_WIDTH       : integer
      );
    port(
      sys_clk              : in    std_logic;
      clk_ref              : in    std_logic;
      sys_rst              : in    std_logic;
      ddr3_ck_p            : out   std_logic_vector(CK_WIDTH-1 downto 0);
      ddr3_ck_n            : out   std_logic_vector(CK_WIDTH-1 downto 0);
      ddr3_addr            : out   std_logic_vector(ROW_WIDTH-1 downto 0);
      ddr3_ba              : out   std_logic_vector(BANK_WIDTH-1 downto 0);
      ddr3_ras_n           : out   std_logic;
      ddr3_cas_n           : out   std_logic;
      ddr3_we_n            : out   std_logic;
      ddr3_cs_n            : out   std_logic_vector((CS_WIDTH*nCS_PER_RANK)-1 downto 0);
      ddr3_cke             : out   std_logic_vector(CKE_WIDTH-1 downto 0);
      ddr3_odt             : out   std_logic_vector((CS_WIDTH*nCS_PER_RANK)-1 downto 0);
      ddr3_reset_n         : out   std_logic;
      ddr3_dm              : out   std_logic_vector(DM_WIDTH-1 downto 0);
      ddr3_dq              : inout std_logic_vector(DQ_WIDTH-1 downto 0);
      ddr3_dqs_p           : inout std_logic_vector(DQS_WIDTH-1 downto 0);
      ddr3_dqs_n           : inout std_logic_vector(DQS_WIDTH-1 downto 0);
      app_wdf_wren         : in    std_logic;
      app_wdf_data         : in    std_logic_vector((4*PAYLOAD_WIDTH)-1 downto 0);
      app_wdf_mask         : in    std_logic_vector((4*PAYLOAD_WIDTH)/8-1 downto 0);
      app_wdf_end          : in    std_logic;
      app_addr             : in    std_logic_vector(ADDR_WIDTH-1 downto 0);
      app_cmd              : in    std_logic_vector(2 downto 0);
      app_en               : in    std_logic;
      app_rdy              : out   std_logic;
      app_wdf_rdy          : out   std_logic;
      app_rd_data          : out   std_logic_vector((4*PAYLOAD_WIDTH)-1 downto 0);
      app_rd_data_end      : out   std_logic;
      app_rd_data_valid    : out   std_logic;
      ui_clk_sync_rst      : out   std_logic;
      ui_clk               : out   std_logic;
      phy_init_done        : out   std_logic
       );
  end component ddr3_ram;

  component init_mem_pattern_ctr
    generic (
      FAMILY             : string;
      TST_MEM_INSTR_MODE : STRING;
      MEM_BURST_LEN      : integer;
      BEGIN_ADDRESS      : std_logic_vector(31 downto 0);
      END_ADDRESS        : std_logic_vector(31 downto 0);
      ADDR_WIDTH         : integer;
      DWIDTH             : integer;
      DATA_MODE          : std_logic_vector(3 downto 0);
      EYE_TEST           : string
      );
    port(
      clk_i               : in  std_logic;
      rst_i               : in  std_logic;
      --mcb_cmd_addr_i      : in  std_logic_vector(ADDR_WIDTH-1 downto 0);
      mcb_cmd_bl_i        : in  std_logic_vector(5 downto 0);
      mcb_cmd_en_i        : in  std_logic;
      mcb_cmd_instr_i     : in  std_logic_vector(2 downto 0);
      mcb_wr_en_i         : in  std_logic;
      vio_modify_enable   : in  std_logic;
      vio_data_mode_value : in  std_logic_vector(2 downto 0);
      vio_addr_mode_value : in  std_logic_vector(2 downto 0);
      vio_bl_mode_value   : in  std_logic_vector(1 downto 0);
      vio_fixed_bl_value  : in  std_logic_vector(5 downto 0);
      mcb_init_done_i     : in  std_logic;
      cmp_error           : in  std_logic;
      run_traffic_o       : out std_logic;
      start_addr_o        : out std_logic_vector(31 downto 0);
      end_addr_o          : out std_logic_vector(31 downto 0);
      cmd_seed_o          : out std_logic_vector(31 downto 0);
      data_seed_o         : out std_logic_vector(31 downto 0);
      load_seed_o         : out std_logic;
      addr_mode_o         : out std_logic_vector(2 downto 0);
      instr_mode_o        : out std_logic_vector(3 downto 0);
      bl_mode_o           : out std_logic_vector(1 downto 0);
      data_mode_o         : out std_logic_vector(3 downto 0);
      mode_load_o         : out std_logic;
      fixed_bl_o          : out std_logic_vector(5 downto 0);
      fixed_instr_o       : out std_logic_vector(2 downto 0);
      fixed_addr_o        : out std_logic_vector(31 downto 0)
      );
  end component init_mem_pattern_ctr;

  component mcb_traffic_gen
    generic(
      FAMILY               : string;
      MEM_BURST_LEN        : integer;
      PORT_MODE            : string;
      DATA_PATTERN         : string;
      CMD_PATTERN          : string;
      ADDR_WIDTH           : integer;
      MEM_COL_WIDTH        : integer;
      NUM_DQ_PINS          : integer;
      SEL_VICTIM_LINE      : integer;
      DWIDTH               : integer;
      DQ_ERROR_WIDTH       : integer;
      EYE_TEST             : string;
      PRBS_EADDR_MASK_POS  : std_logic_vector(31 downto 0);
      PRBS_SADDR_MASK_POS  : std_logic_vector(31 downto 0);
      PRBS_EADDR           : std_logic_vector(31 downto 0);
      PRBS_SADDR           : std_logic_vector(31 downto 0)
      );
    port(
      clk_i              : in  std_logic;
      rst_i              : in  std_logic;
      run_traffic_i      : in  std_logic;
      manual_clear_error : in  std_logic;
      start_addr_i       : in  std_logic_vector(31 downto 0);
      end_addr_i         : in  std_logic_vector(31 downto 0);
      cmd_seed_i         : in  std_logic_vector(31 downto 0);
      data_seed_i        : in  std_logic_vector(31 downto 0);
      load_seed_i        : in  std_logic;
      addr_mode_i        : in  std_logic_vector(2 downto 0);
      instr_mode_i       : in  std_logic_vector(3 downto 0);
      bl_mode_i          : in  std_logic_vector(1 downto 0);
      data_mode_i        : in  std_logic_vector(3 downto 0);
      mode_load_i        : in  std_logic;
      fixed_bl_i         : in  std_logic_vector(5 downto 0);
      fixed_instr_i      : in  std_logic_vector(2 downto 0);
      fixed_addr_i       : in  std_logic_vector(31 downto 0);
      bram_cmd_i         : in  std_logic_vector(38 downto 0);
      bram_valid_i       : in  std_logic;
      fixed_data_i       : in  std_logic_vector(DWIDTH-1 downto 0);
      bram_rdy_o         : out std_logic;
      mcb_cmd_en_o       : out std_logic;
      mcb_cmd_instr_o    : out std_logic_vector(2 downto 0);
      mcb_cmd_addr_o     : out std_logic_vector(ADDR_WIDTH-1 downto 0);
      mcb_cmd_bl_o       : out std_logic_vector(5 downto 0);
      mcb_cmd_full_i     : in  std_logic;
      mcb_wr_en_o        : out std_logic;
      mcb_wr_data_o      : out std_logic_vector(DWIDTH-1 downto 0);
      mcb_wr_data_end_o  : out std_logic;
      mcb_wr_mask_o      : out std_logic_vector((DWIDTH/8) - 1 downto 0);
      mcb_wr_full_i      : in  std_logic;
      mcb_wr_fifo_counts : in  std_logic_vector(6 downto 0);
      mcb_rd_en_o        : out std_logic;
      mcb_rd_data_i      : in  std_logic_vector(DWIDTH-1 downto 0);
      mcb_rd_empty_i     : in  std_logic;
      mcb_rd_fifo_counts : in  std_logic_vector(6 downto 0);
      counts_rst         : in  std_logic;
      wr_data_counts     : out std_logic_vector(47 downto 0);
      rd_data_counts     : out std_logic_vector(47 downto 0);
      error              : out std_logic;
      cmp_data_valid     : out std_logic;
      error_status       : out std_logic_vector(64+((2*dwidth)-1) downto 0);
      cmp_error          : out std_logic;
      cmp_data           : out std_logic_vector(DWIDTH-1 downto 0);
      mem_rd_data        : out std_logic_vector(DWIDTH-1 downto 0);
      dq_error_bytelane_cmp : out std_logic_vector(DQ_ERROR_WIDTH -1 downto 0);
      cumlative_dq_lane_error : out std_logic_vector(DQ_ERROR_WIDTH -1 downto 0)
      );
  end component mcb_traffic_gen;

  component ddr3_model
    port(
      rst_n   : in    std_logic;
      ck      : in    std_logic;
      ck_n    : in    std_logic;
      cke     : in    std_logic;
      cs_n    : in    std_logic;
      ras_n   : in    std_logic;
      cas_n   : in    std_logic;
      we_n    : in    std_logic;
      dm_tdqs : inout std_logic_vector((MEMORY_WIDTH/16) downto 0);
      ba      : in    std_logic_vector(BANK_WIDTH-1 downto 0);
      addr    : in    std_logic_vector(ROW_WIDTH-1 downto 0);
      dq      : inout std_logic_vector(MEMORY_WIDTH-1 downto 0);
      dqs     : inout std_logic_vector((MEMORY_WIDTH/16) downto 0);
      dqs_n   : inout std_logic_vector((MEMORY_WIDTH/16) downto 0);
      tdqs_n  : out   std_logic_vector((MEMORY_WIDTH/16) downto 0);
      odt     : in    std_logic
      );
  end component ddr3_model;

  --**************************************************************************--
  -- Wire Declarations
  --**************************************************************************--
  signal sys_clk   : std_logic := '0';
  signal clk_ref   : std_logic := '0';
  signal sys_rst_n : std_logic := '0';
  signal sys_rst   : std_logic;



  signal ddr3_dm_sdram_tmp : std_logic_vector(DM_WIDTH-1 downto 0);


  signal error            : std_logic;
  signal phy_init_done    : std_logic;
  signal ddr3_parity      : std_logic;
  signal ddr3_reset_n     : std_logic;
  signal sda              : std_logic;
  signal scl              : std_logic;

  signal ddr3_dq_fpga     : std_logic_vector(DQ_WIDTH-1 downto 0);
  signal ddr3_addr_fpga   : std_logic_vector(ROW_WIDTH-1 downto 0);
  signal ddr3_ba_fpga     : std_logic_vector(BANK_WIDTH-1 downto 0);
  signal ddr3_ras_n_fpga  : std_logic;
  signal ddr3_cas_n_fpga  : std_logic;
  signal ddr3_we_n_fpga   : std_logic;
  signal ddr3_cs_n_fpga   : std_logic_vector((CS_WIDTH*nCS_PER_RANK)-1 downto 0);
  signal ddr3_odt_fpga    : std_logic_vector((CS_WIDTH*nCS_PER_RANK)-1 downto 0);
  signal ddr3_cke_fpga    : std_logic_vector(CKE_WIDTH-1 downto 0);
  signal ddr3_dm_fpga     : std_logic_vector(DM_WIDTH-1 downto 0);
  signal ddr3_dqs_p_fpga  : std_logic_vector(DQS_WIDTH-1 downto 0);
  signal ddr3_dqs_n_fpga  : std_logic_vector(DQS_WIDTH-1 downto 0);
  signal ddr3_ck_p_fpga   : std_logic_vector(CK_WIDTH-1 downto 0);
  signal ddr3_ck_n_fpga   : std_logic_vector(CK_WIDTH-1 downto 0);

  signal ddr3_dq_sdram    : std_logic_vector(DQ_WIDTH-1 downto 0);
  signal ddr3_addr_sdram  : std_logic_vector(ROW_WIDTH-1 downto 0);
  signal ddr3_ba_sdram    : std_logic_vector(BANK_WIDTH-1 downto 0);
  signal ddr3_ras_n_sdram : std_logic;
  signal ddr3_cas_n_sdram : std_logic;
  signal ddr3_we_n_sdram  : std_logic;
  signal ddr3_cs_n_sdram  : std_logic_vector((CS_WIDTH*nCS_PER_RANK)-1 downto 0);
  signal ddr3_odt_sdram   : std_logic_vector((CS_WIDTH*nCS_PER_RANK)-1 downto 0);
  signal ddr3_cke_sdram   : std_logic_vector(CKE_WIDTH-1 downto 0);
  signal ddr3_dm_sdram    : std_logic_vector(DM_WIDTH-1 downto 0);
  signal ddr3_dqs_p_sdram : std_logic_vector(DQS_WIDTH-1 downto 0);
  signal ddr3_dqs_n_sdram : std_logic_vector(DQS_WIDTH-1 downto 0);
  signal ddr3_ck_p_sdram  : std_logic_vector(CK_WIDTH-1 downto 0);
  signal ddr3_ck_n_sdram  : std_logic_vector(CK_WIDTH-1 downto 0);

  signal ddr3_dm_sdram_xtrabits    : std_logic_vector(1 downto 0);
  signal ddr3_dqs_p_sdram_xtrabits : std_logic_vector(1 downto 0) := "00";
  signal ddr3_dqs_n_sdram_xtrabits : std_logic_vector(1 downto 0) := "00";
  signal ddr3_dq_sdram_xtrabits    : std_logic_vector(15 downto 0) := X"0000";

  signal ddr3_addr_r      : std_logic_vector(ROW_WIDTH-1 downto 0);
  signal ddr3_ba_r        : std_logic_vector(BANK_WIDTH-1 downto 0);
  signal ddr3_ras_n_r     : std_logic;
  signal ddr3_cas_n_r     : std_logic;
  signal ddr3_we_n_r      : std_logic;
  signal ddr3_cs_n_r      : std_logic_vector((CS_WIDTH*nCS_PER_RANK)-1 downto 0);
  signal ddr3_odt_r       : std_logic_vector((CS_WIDTH*nCS_PER_RANK)-1 downto 0);
  signal ddr3_cke_r       : std_logic_vector(CKE_WIDTH-1 downto 0);


  signal clk                   : std_logic;
  signal rst                   : std_logic;
  signal app_en                : std_logic;
  signal app_cmd               : std_logic_vector(2 downto 0);
  signal app_addr              : std_logic_vector(ADDR_WIDTH-1 downto 0);
  signal app_wdf_wren          : std_logic;
  signal app_wdf_data          : std_logic_vector(APP_DATA_WIDTH-1 downto 0);
  signal app_wdf_mask          : std_logic_vector(APP_MASK_WIDTH-1 downto 0) := (others => '0');
  signal app_wdf_end           : std_logic;
  signal tg_wr_fifo_counts     : std_logic_vector(6 downto 0);
  signal tg_rd_fifo_counts     : std_logic_vector(6 downto 0);
  signal tg_rd_en              : std_logic;
  signal app_rd_data           : std_logic_vector(APP_DATA_WIDTH-1 downto 0);
  signal tpt_hdata             : std_logic_vector(31 downto 0);
  signal t_gen_run_traffic     : std_logic;
  signal t_gen_start_addr      : std_logic_vector(31 downto 0);
  signal t_gen_end_addr        : std_logic_vector(31 downto 0);
  signal t_gen_cmd_seed        : std_logic_vector(31 downto 0);
  signal t_gen_data_seed       : std_logic_vector(31 downto 0);
  signal t_gen_load_seed       : std_logic;
  signal t_gen_addr_mode       : std_logic_vector(2 downto 0);
  signal t_gen_instr_mode      : std_logic_vector(3 downto 0);
  signal t_gen_bl_mode         : std_logic_vector(1 downto 0);
  signal t_gen_data_mode       : std_logic_vector(3 downto 0);
  signal t_gen_mode_load       : std_logic;
  signal t_gen_fixed_bl        : std_logic_vector(5 downto 0);
  signal t_gen_fixed_instr     : std_logic_vector(2 downto 0);
  signal t_gen_fixed_addr      : std_logic_vector(31 downto 0);
  signal manual_clear_error    : std_logic;
  signal modify_enable_sel     : std_logic;
  signal app_rdy               : std_logic;
  signal app_rdy_i             : std_logic;
  signal app_wdf_rdy           : std_logic;
  signal app_wdf_rdy_i         : std_logic;
  signal app_rd_data_end       : std_logic;
  signal app_rd_data_valid     : std_logic;
  signal not_app_rd_data_valid : std_logic;
  signal vio_data_mode         : std_logic_vector(2 downto 0);
  signal vio_addr_mode         : std_logic_vector(2 downto 0);

begin

  --**************************************************************************--
  -- Clock generation and reset
  --**************************************************************************--

  sys_rst_n <= '1' after 120000 ps;
  sys_rst <= sys_rst_n when (RST_ACT_LOW = 1) else
             not (sys_rst_n);

  -- Generate system clock = twice rate of CLK
  sys_clk <= not sys_clk after (CLK_PERIOD/2);

  -- Generate IDELAYCTRL reference clock (200MHz)
  clk_ref <= not clk_ref after (REFCLK_HALF_PERIOD);


  app_rdy_i     <= not(app_rdy);
  app_wdf_rdy_i <= not(app_wdf_rdy);

  --**************************************************************************--

  ddr3_ck_p_sdram   <=  transport ddr3_ck_p_fpga  after TPROP_PCB_CTRL;
  ddr3_ck_n_sdram   <=  transport ddr3_ck_n_fpga  after TPROP_PCB_CTRL;
  ddr3_addr_sdram   <=  transport ddr3_addr_fpga  after TPROP_PCB_CTRL;
  ddr3_ba_sdram     <=  transport ddr3_ba_fpga    after TPROP_PCB_CTRL;
  ddr3_ras_n_sdram  <=  transport ddr3_ras_n_fpga after TPROP_PCB_CTRL;
  ddr3_cas_n_sdram  <=  transport ddr3_cas_n_fpga after TPROP_PCB_CTRL;
  ddr3_we_n_sdram   <=  transport ddr3_we_n_fpga  after TPROP_PCB_CTRL;
  ddr3_cs_n_sdram   <=  transport ddr3_cs_n_fpga  after TPROP_PCB_CTRL;
  ddr3_cke_sdram    <=  transport ddr3_cke_fpga   after TPROP_PCB_CTRL;
  ddr3_odt_sdram    <=  transport ddr3_odt_fpga   after TPROP_PCB_CTRL;
  ddr3_dm_sdram_tmp <=  transport ddr3_dm_fpga    after TPROP_PCB_DATA; --DM signal generation


  ddr3_dm_sdram <= ddr3_dm_sdram_tmp;

-- Controlling the bi-directional BUS
  dq_delay : for dqwd in 1 to DQ_WIDTH-1 generate
    u_delay_dq : WireDelay
      generic map(
        Delay_g    => TPROP_PCB_DATA,
        Delay_rd   => TPROP_PCB_DATA_RD,
        ERR_INSERT => "OFF"
        )
      port map(
        A             => ddr3_dq_fpga(dqwd),
        B             => ddr3_dq_sdram(dqwd),
        reset         => sys_rst_n,
        phy_init_done => phy_init_done
        );

    u_delay_dq_0 : WireDelay
      generic map(
        Delay_g    => TPROP_PCB_DATA,
        Delay_rd   => TPROP_PCB_DATA_RD,
        ERR_INSERT => ECC
        )
      port map(
        A             => ddr3_dq_fpga(0),
        B             => ddr3_dq_sdram(0),
        reset         => sys_rst_n,
        phy_init_done => phy_init_done
        );
  end generate dq_delay;

  dqs_delay : for dqswd in 0 to DQS_WIDTH-1 generate
    u_delay_dqs_p : WireDelay
      generic map(
        Delay_g    => TPROP_DQS,
        Delay_rd   => TPROP_DQS_RD,
        ERR_INSERT => "OFF"
        )
      port map(
        A             => ddr3_dqs_p_fpga(dqswd),
        B             => ddr3_dqs_p_sdram(dqswd),
        reset         => sys_rst_n,
        phy_init_done => phy_init_done
        );

    u_delay_dqs_n : WireDelay
      generic map(
        Delay_g    => TPROP_DQS,
        Delay_rd   => TPROP_DQS_RD,
        ERR_INSERT => "OFF"
        )
      port map(
        A             => ddr3_dqs_n_fpga(dqswd),
        B             => ddr3_dqs_n_sdram(dqswd),
        reset         => sys_rst_n,
        phy_init_done => phy_init_done
        );
  end generate dqs_delay;

  sda <= '1';
  scl <= '1';

  u_ip_top : ddr3_ram
    generic map(
      nCK_PER_CLK        => nCK_PER_CLK,
      tCK                => tCK,
      RST_ACT_LOW        => RST_ACT_LOW,
      REFCLK_FREQ        => REFCLK_FREQ,
      IODELAY_GRP => IODELAY_GRP,
      INPUT_CLK_TYPE     => INPUT_CLK_TYPE,
      BANK_WIDTH         => BANK_WIDTH,
      CK_WIDTH           => CK_WIDTH,
      CKE_WIDTH          => CKE_WIDTH,
      COL_WIDTH          => COL_WIDTH,
      nCS_PER_RANK       => nCS_PER_RANK,
      DQ_WIDTH           => DQ_WIDTH,
      DM_WIDTH             => DM_WIDTH,
      DQS_CNT_WIDTH      => DQS_CNT_WIDTH,
      DQS_WIDTH          => DQS_WIDTH,
      ROW_WIDTH          => ROW_WIDTH,
      RANK_WIDTH         => RANK_WIDTH,
      CS_WIDTH           => CS_WIDTH,
      BURST_MODE         => BURST_MODE,
      BM_CNT_WIDTH       => BM_CNT_WIDTH,
      CLKFBOUT_MULT_F    => CLKFBOUT_MULT_F,
      DIVCLK_DIVIDE      => DIVCLK_DIVIDE,
      CLKOUT_DIVIDE      => CLKOUT_DIVIDE,
      OUTPUT_DRV         => OUTPUT_DRV,
      REG_CTRL           => REG_CTRL,
      RTT_NOM            => RTT_NOM,
      RTT_WR             => RTT_WR,
      SIM_BYPASS_INIT_CAL=> SIM_BYPASS_INIT_CAL,
      DEBUG_PORT         => DEBUG_PORT,
      ADDR_CMD_MODE      => ADDR_CMD_MODE,
      ORDERING           => ORDERING,
      STARVE_LIMIT       => STARVE_LIMIT,
      tPRDI              => tPRDI,
      tREFI              => tREFI,
      tZQI               => tZQI,
      ADDR_WIDTH         => ADDR_WIDTH,
      ECC                => ECC,
      ECC_TEST           => ECC_TEST,
      TCQ                  => TCQ,
      DATA_WIDTH           => DATA_WIDTH,
      PAYLOAD_WIDTH        => PAYLOAD_WIDTH
      )
    port map(

      sys_clk              => sys_clk,
      clk_ref              => clk_ref,
      sys_rst              => sys_rst,
      ddr3_ck_p            => ddr3_ck_p_fpga,
      ddr3_ck_n            => ddr3_ck_n_fpga,
      ddr3_addr            => ddr3_addr_fpga,
      ddr3_ba              => ddr3_ba_fpga,
      ddr3_ras_n           => ddr3_ras_n_fpga,
      ddr3_cas_n           => ddr3_cas_n_fpga,
      ddr3_we_n            => ddr3_we_n_fpga,
      ddr3_cs_n            => ddr3_cs_n_fpga,
      ddr3_cke             => ddr3_cke_fpga,
      ddr3_odt             => ddr3_odt_fpga,
      ddr3_reset_n         => ddr3_reset_n,
      ddr3_dm              => ddr3_dm_fpga,
      ddr3_dq              => ddr3_dq_fpga,
      ddr3_dqs_p           => ddr3_dqs_p_fpga,
      ddr3_dqs_n           => ddr3_dqs_n_fpga,
      ui_clk               => clk,
      ui_clk_sync_rst      => rst,
      app_wdf_wren         => app_wdf_wren,
      app_wdf_data         => app_wdf_data,
      app_wdf_mask         => app_wdf_mask,
      app_wdf_end          => app_wdf_end,
      app_addr             => app_addr,
      app_en               => app_en,
      app_cmd              => app_cmd,
      app_rdy              => app_rdy,
      app_wdf_rdy          => app_wdf_rdy,
      app_rd_data          => app_rd_data,
      app_rd_data_end      => app_rd_data_end,
      app_rd_data_valid    => app_rd_data_valid,
      phy_init_done        => phy_init_done
       );

  -- Extra one clock pipelining for RDIMM address and
  -- control signals is implemented here (Implemented external to memory model)
  process (ddr3_ck_p_sdram(0))
  begin
    if(rising_edge(ddr3_ck_p_sdram(0))) then
      if(ddr3_reset_n = '0') then
        ddr3_ras_n_r <= '1';
        ddr3_cas_n_r <= '1';
        ddr3_we_n_r  <= '1';
        ddr3_cs_n_r  <= (others => '1');
        ddr3_odt_r   <= (others => '0');
      else
        ddr3_addr_r  <= ddr3_addr_sdram  after (CLK_PERIOD/2);
        ddr3_ba_r    <= ddr3_ba_sdram    after (CLK_PERIOD/2);
        ddr3_ras_n_r <= ddr3_ras_n_sdram after (CLK_PERIOD/2);
        ddr3_cas_n_r <= ddr3_cas_n_sdram after (CLK_PERIOD/2);
        ddr3_we_n_r  <= ddr3_we_n_sdram  after (CLK_PERIOD/2);

        if (CS_WIDTH > 1 or nCS_PER_RANK > 1) then
          if ((ddr3_cs_n_sdram(0) = '0' or ddr3_cs_n_sdram(1) = '0') and (phy_init_done = '0')) then
            ddr3_cs_n_r  <= (others => '1')  after (CLK_PERIOD/2);
          else
            ddr3_cs_n_r  <= ddr3_cs_n_sdram  after (CLK_PERIOD/2);
          end if;
        else
            ddr3_cs_n_r  <= ddr3_cs_n_sdram  after (CLK_PERIOD/2);
        end if;

        ddr3_odt_r   <= ddr3_odt_sdram   after (CLK_PERIOD/2);
      end if;
    end if;
  end process;

  -- to avoid tIS violations on CKE when reset is deasserted
  process (ddr3_ck_n_sdram(0))
  begin
    if(rising_edge(ddr3_ck_n_sdram(0))) then
      if(ddr3_reset_n = '0') then
        ddr3_cke_r <= (others => '0');
      else
        ddr3_cke_r <= ddr3_cke_sdram after CLK_PERIOD;
      end if;
    end if;
  end process;

  --***************************************************************************
  -- Instantiate memories
  --***************************************************************************

  comp_inst : if (DRAM_DEVICE = "COMP") generate
    mem_rnk : for r in 0 to CS_WIDTH-1 generate
      mem_16 : if (MEMORY_WIDTH = 16) generate
        gen_mem_gt16 : if (DQ_WIDTH/16 >= 1) generate
            gen_mem : for i in 0 to NUM_COMP-1 generate
              u_comp_ddr3 : ddr3_model
                port map(
                  rst_n   => ddr3_reset_n,
                  ck      => ddr3_ck_p_sdram(0),
                  ck_n    => ddr3_ck_n_sdram(0),
                  cke     => ddr3_cke_sdram(r),
                  cs_n    => ddr3_cs_n_sdram(r),
                  ras_n   => ddr3_ras_n_sdram,
                  cas_n   => ddr3_cas_n_sdram,
                  we_n    => ddr3_we_n_sdram,
                  dm_tdqs => ddr3_dm_sdram((2*(i+1)-1) downto (2*i)),
                  ba      => ddr3_ba_sdram,
                  addr    => ddr3_addr_sdram,
                  dq      => ddr3_dq_sdram(16*(i+1)-1 downto 16*(i)),
                  dqs     => ddr3_dqs_p_sdram((2*(i+1)-1) downto (2*i)),
                  dqs_n   => ddr3_dqs_n_sdram((2*(i+1)-1) downto (2*i)),
                  tdqs_n  => open,
                  odt     => ddr3_odt_sdram(r)
                  );
            end generate gen_mem;
        end generate gen_mem_gt16;

        gen_mem_extrabits : if (DQ_WIDTH mod 16 /= 0) generate

          dq_xtrabits : for dqx in 0 to 7 generate
            u_dq_xtrabits : WireDelay
              generic map(
                Delay_g    => 0 ps,
                Delay_rd   => 0 ps,
                ERR_INSERT => "OFF"
                )
              port map(
                A             => ddr3_dq_sdram_xtrabits(dqx),
                B             => ddr3_dq_sdram(DQ_WIDTH-8+dqx),
                reset         => sys_rst_n,
                phy_init_done => phy_init_done
                );
          end generate dq_xtrabits;

          u_dqs_p_xtrabits : WireDelay
            generic map(
              Delay_g  => 0 ps,
              Delay_rd => 0 ps,
              ERR_INSERT => "OFF"
              )
            port map(
              A             => ddr3_dqs_p_sdram_xtrabits(0),
              B             => ddr3_dqs_p_sdram(DQS_WIDTH-1),
              reset         => sys_rst_n,
              phy_init_done => phy_init_done
              );

          u_dqs_n_xtrabits : WireDelay
            generic map(
              Delay_g  => 0 ps,
              Delay_rd => 0 ps,
              ERR_INSERT => "OFF"
              )
            port map(
              A             => ddr3_dqs_n_sdram_xtrabits(0),
              B             => ddr3_dqs_n_sdram(DQS_WIDTH-1),
              reset         => sys_rst_n,
              phy_init_done => phy_init_done
              );

          ddr3_dm_sdram_xtrabits <= (ddr3_dm_sdram(DM_WIDTH-1) & ddr3_dm_sdram(DM_WIDTH-1));
          ddr3_dqs_p_sdram_xtrabits(1) <= ddr3_dqs_p_sdram_xtrabits(0);
          ddr3_dqs_n_sdram_xtrabits(1) <= ddr3_dqs_n_sdram_xtrabits(0);
          ddr3_dq_sdram_xtrabits(15 downto 8) <= ddr3_dq_sdram_xtrabits(7 downto 0);

          u_comp_ddr3 : ddr3_model
            port map(
              rst_n   => ddr3_reset_n,
              ck      => ddr3_ck_p_sdram(0),
              ck_n    => ddr3_ck_n_sdram(0),
              cke     => ddr3_cke_sdram(r),
              cs_n    => ddr3_cs_n_sdram(r),
              ras_n   => ddr3_ras_n_sdram,
              cas_n   => ddr3_cas_n_sdram,
              we_n    => ddr3_we_n_sdram,
              dm_tdqs => ddr3_dm_sdram_xtrabits,
              ba      => ddr3_ba_sdram,
              addr    => ddr3_addr_sdram,
              dq      => ddr3_dq_sdram_xtrabits,
              dqs     => ddr3_dqs_p_sdram_xtrabits,
              dqs_n   => ddr3_dqs_n_sdram_xtrabits,
              tdqs_n  => open,
              odt     => ddr3_odt_sdram(r)
              );
        end generate gen_mem_extrabits;
      end generate mem_16;

      mem_8_4 : if((MEMORY_WIDTH = 8) or (MEMORY_WIDTH = 4)) generate
        gen_mem : for i in 0 to NUM_COMP-1 generate
          u_comp_ddr3 : ddr3_model
            port map(
              rst_n   => ddr3_reset_n,
              ck      => ddr3_ck_p_sdram(0),
              ck_n    => ddr3_ck_n_sdram(0),
              cke     => ddr3_cke_sdram(r),
              cs_n    => ddr3_cs_n_sdram(r),
              ras_n   => ddr3_ras_n_sdram,
              cas_n   => ddr3_cas_n_sdram,
              we_n    => ddr3_we_n_sdram,
              dm_tdqs => ddr3_dm_sdram(i downto i),
              ba      => ddr3_ba_sdram,
              addr    => ddr3_addr_sdram,
              dq      => ddr3_dq_sdram(MEMORY_WIDTH*(i+1)-1 downto MEMORY_WIDTH*(i)),
              dqs     => ddr3_dqs_p_sdram(i downto i),
              dqs_n   => ddr3_dqs_n_sdram(i downto i),
              tdqs_n  => open,
              odt     => ddr3_odt_sdram(r)
              );
        end generate gen_mem;
      end generate mem_8_4;
    end generate mem_rnk;
  end generate comp_inst;

  rdimm_inst : if(DRAM_DEVICE = "RDIMM") generate
    mem_rnk : for r in 0 to CS_WIDTH-1 generate
      mem_8_4 : if((MEMORY_WIDTH = 8) or (MEMORY_WIDTH = 4)) generate
        gen_mem : for i in 0 to NUM_COMP-1 generate
          u_comp_ddr3 : ddr3_model
            port map(
              rst_n   => ddr3_reset_n,
              ck      => ddr3_ck_p_sdram((i*MEMORY_WIDTH)/72),
              ck_n    => ddr3_ck_n_sdram((i*MEMORY_WIDTH)/72),
              cke     => ddr3_cke_r(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
              cs_n    => ddr3_cs_n_r(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
              ras_n   => ddr3_ras_n_r,
              cas_n   => ddr3_cas_n_r,
              we_n    => ddr3_we_n_r,
              dm_tdqs => ddr3_dm_sdram(i downto i),
              ba      => ddr3_ba_r,
              addr    => ddr3_addr_r,
              dq      => ddr3_dq_sdram(MEMORY_WIDTH*(i+1)-1 downto MEMORY_WIDTH*(i)),
              dqs     => ddr3_dqs_p_sdram(i downto i),
              dqs_n   => ddr3_dqs_n_sdram(i downto i),
              tdqs_n  => open,
              odt     => ddr3_odt_r(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r))
              );
        end generate gen_mem;
      end generate mem_8_4;
    end generate mem_rnk;
  end generate rdimm_inst;

  udimm_inst : if(DRAM_DEVICE = "UDIMM") generate
    mem_rnk : for r in 0 to CS_WIDTH-1 generate
      mem_16 : if (MEMORY_WIDTH = 16) generate
        gen_mem_gt16 : if (DQ_WIDTH/16 > 1) generate
          gen_mem : for i in 0 to NUM_COMP-1 generate
            u_comp_ddr3 : ddr3_model
              port map(
                rst_n   => ddr3_reset_n,
                ck      => ddr3_ck_p_sdram((i*MEMORY_WIDTH)/72),
                ck_n    => ddr3_ck_n_sdram((i*MEMORY_WIDTH)/72),
                cke     => ddr3_cke_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
                cs_n    => ddr3_cs_n_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
                ras_n   => ddr3_ras_n_sdram,
                cas_n   => ddr3_cas_n_sdram,
                we_n    => ddr3_we_n_sdram,
                dm_tdqs => ddr3_dm_sdram((2*(i+1)-1) downto (2*i)),
                ba      => ddr3_ba_sdram,
                addr    => ddr3_addr_sdram,
                dq      => ddr3_dq_sdram(16*(i+1)-1 downto 16*(i)),
                dqs     => ddr3_dqs_p_sdram((2*(i+1)-1) downto (2*i)),
                dqs_n   => ddr3_dqs_n_sdram((2*(i+1)-1) downto (2*i)),
                tdqs_n  => open,
                odt     => ddr3_odt_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r))
                );
          end generate gen_mem;
        end generate gen_mem_gt16;

        gen_mem_extrabits : if (DQ_WIDTH mod 16 /= 0) generate

          dq_xtrabits : for dqx in 0 to 7 generate
            u_dq_xtrabits : WireDelay
              generic map(
                Delay_g  => 0 ps,
                Delay_rd => 0 ps,
                ERR_INSERT => "OFF"
                )
              port map(
                A             => ddr3_dq_sdram_xtrabits(dqx),
                B             => ddr3_dq_sdram(DQ_WIDTH-8+dqx),
                reset         => sys_rst_n,
                phy_init_done => phy_init_done
                );
          end generate dq_xtrabits;

          u_dqs_p_xtrabits : WireDelay
            generic map(
              Delay_g  => 0 ps,
              Delay_rd => 0 ps,
              ERR_INSERT => "OFF"
              )
            port map(
              A             => ddr3_dqs_p_sdram_xtrabits(0),
              B             => ddr3_dqs_p_sdram(DQS_WIDTH-1),
              reset         => sys_rst_n,
              phy_init_done => phy_init_done
              );

          u_dqs_n_xtrabits : WireDelay
            generic map(
              Delay_g  => 0 ps,
              Delay_rd => 0 ps,
              ERR_INSERT => "OFF"
              )
            port map(
              A             => ddr3_dqs_n_sdram_xtrabits(0),
              B             => ddr3_dqs_n_sdram(DQS_WIDTH-1),
              reset         => sys_rst_n,
              phy_init_done => phy_init_done
              );

          ddr3_dm_sdram_xtrabits <= (ddr3_dm_sdram(DM_WIDTH-1) & ddr3_dm_sdram(DM_WIDTH-1));
          ddr3_dqs_p_sdram_xtrabits(1) <= ddr3_dqs_p_sdram_xtrabits(0);
          ddr3_dqs_n_sdram_xtrabits(1) <= ddr3_dqs_n_sdram_xtrabits(0);
          ddr3_dq_sdram_xtrabits(15 downto 8) <= ddr3_dq_sdram_xtrabits(7 downto 0);

          u_comp_ddr3 : ddr3_model
            port map(
              rst_n   => ddr3_reset_n,
              ck      => ddr3_ck_p_sdram((DQ_WIDTH-1)/72),
              ck_n    => ddr3_ck_n_sdram((DQ_WIDTH-1)/72),
              cke     => ddr3_cke_sdram(((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)),
              cs_n    => ddr3_cs_n_sdram(((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)),
              ras_n   => ddr3_ras_n_sdram,
              cas_n   => ddr3_cas_n_sdram,
              we_n    => ddr3_we_n_sdram,
              dm_tdqs => ddr3_dm_sdram_xtrabits,
              ba      => ddr3_ba_sdram,
              addr    => ddr3_addr_sdram,
              dq      => ddr3_dq_sdram_xtrabits,
              dqs     => ddr3_dqs_p_sdram_xtrabits,
              dqs_n   => ddr3_dqs_n_sdram_xtrabits,
              tdqs_n  => open,
              odt     => ddr3_odt_sdram(((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r))
              );
        end generate gen_mem_extrabits;
      end generate mem_16;

      mem_8_4 : if((MEMORY_WIDTH = 8) or (MEMORY_WIDTH = 4)) generate
        gen_mem : for i in 0 to NUM_COMP-1 generate
          u_comp_ddr3 : ddr3_model
            port map(
              rst_n   => ddr3_reset_n,
              ck      => ddr3_ck_p_sdram((i*MEMORY_WIDTH)/72),
              ck_n    => ddr3_ck_n_sdram((i*MEMORY_WIDTH)/72),
              cke     => ddr3_cke_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
              cs_n    => ddr3_cs_n_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
              ras_n   => ddr3_ras_n_sdram,
              cas_n   => ddr3_cas_n_sdram,
              we_n    => ddr3_we_n_sdram,
              dm_tdqs => ddr3_dm_sdram(i downto i),
              ba      => ddr3_ba_sdram,
              addr    => ddr3_addr_sdram,
              dq      => ddr3_dq_sdram(MEMORY_WIDTH*(i+1)-1 downto MEMORY_WIDTH*(i)),
              dqs     => ddr3_dqs_p_sdram(i downto i),
              dqs_n   => ddr3_dqs_n_sdram(i downto i),
              tdqs_n  => open,
              odt     => ddr3_odt_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r))
              );
        end generate gen_mem;
      end generate mem_8_4;
    end generate mem_rnk;
  end generate udimm_inst;

  sodimm_inst : if(DRAM_DEVICE = "SODIMM") generate
    mem_rnk : for r in 0 to CS_WIDTH-1 generate
      mem_16 : if (MEMORY_WIDTH = 16) generate
        gen_mem_gt16 : if (DQ_WIDTH/16 > 1) generate
          gen_mem : for i in 0 to NUM_COMP-1 generate
            u_comp_ddr3 : ddr3_model
              port map(
                rst_n   => ddr3_reset_n,
                ck      => ddr3_ck_p_sdram((i*MEMORY_WIDTH)/72),
                ck_n    => ddr3_ck_n_sdram((i*MEMORY_WIDTH)/72),
                cke     => ddr3_cke_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
                cs_n    => ddr3_cs_n_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
                ras_n   => ddr3_ras_n_sdram,
                cas_n   => ddr3_cas_n_sdram,
                we_n    => ddr3_we_n_sdram,
                dm_tdqs => ddr3_dm_sdram((2*(i+1)-1) downto (2*i)),
                ba      => ddr3_ba_sdram,
                addr    => ddr3_addr_sdram,
                dq      => ddr3_dq_sdram(16*(i+1)-1 downto 16*(i)),
                dqs     => ddr3_dqs_p_sdram((2*(i+1)-1) downto (2*i)),
                dqs_n   => ddr3_dqs_n_sdram((2*(i+1)-1) downto (2*i)),
                tdqs_n  => open,
                odt     => ddr3_odt_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r))
                );
          end generate gen_mem;
        end generate gen_mem_gt16;

        gen_mem_extrabits : if (DQ_WIDTH mod 16 /= 0) generate

          dq_xtrabits : for dqx in 0 to 7 generate
            u_dq_xtrabits : WireDelay
              generic map(
                Delay_g  => 0 ps,
                Delay_rd => 0 ps,
                ERR_INSERT => "OFF"
                )
              port map(
                A             => ddr3_dq_sdram_xtrabits(dqx),
                B             => ddr3_dq_sdram(DQ_WIDTH-8+dqx),
                reset         => sys_rst_n,
                phy_init_done => phy_init_done
                );
          end generate dq_xtrabits;

          u_dqs_p_xtrabits : WireDelay
            generic map(
              Delay_g  => 0 ps,
              Delay_rd => 0 ps,
              ERR_INSERT => "OFF"
              )
            port map(
              A             => ddr3_dqs_p_sdram_xtrabits(0),
              B             => ddr3_dqs_p_sdram(DQS_WIDTH-1),
              reset         => sys_rst_n,
              phy_init_done => phy_init_done
              );

          u_dqs_n_xtrabits : WireDelay
            generic map(
              Delay_g  => 0 ps,
              Delay_rd => 0 ps,
              ERR_INSERT => "OFF"
              )
            port map(
              A             => ddr3_dqs_n_sdram_xtrabits(0),
              B             => ddr3_dqs_n_sdram(DQS_WIDTH-1),
              reset         => sys_rst_n,
              phy_init_done => phy_init_done
              );

          ddr3_dm_sdram_xtrabits <= (ddr3_dm_sdram(DM_WIDTH-1) & ddr3_dm_sdram(DM_WIDTH-1));
          ddr3_dqs_p_sdram_xtrabits(1) <= ddr3_dqs_p_sdram_xtrabits(0);
          ddr3_dqs_n_sdram_xtrabits(1) <= ddr3_dqs_n_sdram_xtrabits(0);
          ddr3_dq_sdram_xtrabits(15 downto 8) <= ddr3_dq_sdram_xtrabits(7 downto 0);

          u_comp_ddr3 : ddr3_model
            port map(
              rst_n   => ddr3_reset_n,
              ck      => ddr3_ck_p_sdram((DQ_WIDTH-1)/72),
              ck_n    => ddr3_ck_n_sdram((DQ_WIDTH-1)/72),
              cke     => ddr3_cke_sdram(((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)),
              cs_n    => ddr3_cs_n_sdram(((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r)),
              ras_n   => ddr3_ras_n_sdram,
              cas_n   => ddr3_cas_n_sdram,
              we_n    => ddr3_we_n_sdram,
              dm_tdqs => ddr3_dm_sdram_xtrabits,
              ba      => ddr3_ba_sdram,
              addr    => ddr3_addr_sdram,
              dq      => ddr3_dq_sdram_xtrabits,
              dqs     => ddr3_dqs_p_sdram_xtrabits,
              dqs_n   => ddr3_dqs_n_sdram_xtrabits,
              tdqs_n  => open,
              odt     => ddr3_odt_sdram(((DQ_WIDTH-1)/72)+(nCS_PER_RANK*r))
              );
        end generate gen_mem_extrabits;
      end generate mem_16;

      mem_8_4 : if((MEMORY_WIDTH = 8) or (MEMORY_WIDTH = 4)) generate
        gen_mem : for i in 0 to NUM_COMP-1 generate
          u_comp_ddr3 : ddr3_model
            port map(
              rst_n   => ddr3_reset_n,
              ck      => ddr3_ck_p_sdram((i*MEMORY_WIDTH)/72),
              ck_n    => ddr3_ck_n_sdram((i*MEMORY_WIDTH)/72),
              cke     => ddr3_cke_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
              cs_n    => ddr3_cs_n_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r)),
              ras_n   => ddr3_ras_n_sdram,
              cas_n   => ddr3_cas_n_sdram,
              we_n    => ddr3_we_n_sdram,
              dm_tdqs => ddr3_dm_sdram(i downto i),
              ba      => ddr3_ba_sdram,
              addr    => ddr3_addr_sdram,
              dq      => ddr3_dq_sdram(MEMORY_WIDTH*(i+1)-1 downto MEMORY_WIDTH*(i)),
              dqs     => ddr3_dqs_p_sdram(i downto i),
              dqs_n   => ddr3_dqs_n_sdram(i downto i),
              tdqs_n  => open,
              odt     => ddr3_odt_sdram(((i*MEMORY_WIDTH)/72)+(nCS_PER_RANK*r))
              );
        end generate gen_mem;
      end generate mem_8_4;
    end generate mem_rnk;
  end generate sodimm_inst;



  -- Traffic Gen Modules
  init_mem0 : init_mem_pattern_ctr
    generic map(
      FAMILY             => "VIRTEX6",
      TST_MEM_INSTR_MODE => TST_MEM_INSTR_MODE,
      MEM_BURST_LEN      => BURST_LENGTH,
      BEGIN_ADDRESS      => BEGIN_ADDRESS,
      END_ADDRESS        => END_ADDRESS,
      DWIDTH             => APP_DATA_WIDTH,
      ADDR_WIDTH         => ADDR_WIDTH,
      DATA_MODE          => DATA_MODE,
      EYE_TEST           => EYE_TEST
      )
    port map(
      clk_i               => clk,
      rst_i               => rst,
      mcb_cmd_en_i        => app_en,
      mcb_cmd_instr_i     => app_cmd(2 downto 0),
      --mcb_cmd_addr_i      => app_addr,
      mcb_cmd_bl_i        => "001000",
      mcb_init_done_i     => phy_init_done,
      cmp_error           => error,
      run_traffic_o       => t_gen_run_traffic,
      start_addr_o        => t_gen_start_addr,
      end_addr_o          => t_gen_end_addr,
      cmd_seed_o          => t_gen_cmd_seed,
      data_seed_o         => t_gen_data_seed,
      load_seed_o         => t_gen_load_seed,
      addr_mode_o         => t_gen_addr_mode,
      instr_mode_o        => t_gen_instr_mode,
      bl_mode_o           => t_gen_bl_mode,
      data_mode_o         => t_gen_data_mode,
      mode_load_o         => t_gen_mode_load,
      fixed_bl_o          => t_gen_fixed_bl,
      fixed_instr_o       => t_gen_fixed_instr,
      fixed_addr_o        => t_gen_fixed_addr,
      mcb_wr_en_i         => app_wdf_wren,
      vio_modify_enable   => modify_enable_sel,
      vio_data_mode_value => vio_data_mode,
      vio_addr_mode_value => vio_addr_mode,
      vio_bl_mode_value   => "01",
      vio_fixed_bl_value  => "001000"
      );

  not_app_rd_data_valid <= not app_rd_data_valid;

  m_traffic_gen : mcb_traffic_gen
    generic map(
      FAMILY              => "VIRTEX6",
      MEM_BURST_LEN       => BURST_LENGTH,
      PORT_MODE           => "BI_MODE",
      DATA_PATTERN        => DATA_PATTERN,
      CMD_PATTERN         => CMD_PATTERN,
      ADDR_WIDTH          => ADDR_WIDTH,
      MEM_COL_WIDTH       => COL_WIDTH,
      NUM_DQ_PINS         => PAYLOAD_WIDTH,
      SEL_VICTIM_LINE     => SEL_VICTIM_LINE,
      DWIDTH              => APP_DATA_WIDTH,
      DQ_ERROR_WIDTH      => PAYLOAD_WIDTH/8,
      PRBS_SADDR_MASK_POS => PRBS_SADDR_MASK_POS,
      PRBS_EADDR_MASK_POS => PRBS_EADDR_MASK_POS,
      PRBS_SADDR          => BEGIN_ADDRESS,
      PRBS_EADDR          => END_ADDRESS,
      EYE_TEST            => EYE_TEST
      )
    port map(
      clk_i              => clk,
      rst_i              => rst,
      run_traffic_i      => t_gen_run_traffic,
      manual_clear_error => manual_clear_error,
      start_addr_i       => t_gen_start_addr,
      end_addr_i         => t_gen_end_addr,
      cmd_seed_i         => t_gen_cmd_seed,
      data_seed_i        => t_gen_data_seed,
      load_seed_i        => t_gen_load_seed,
      addr_mode_i        => t_gen_addr_mode,
      instr_mode_i       => t_gen_instr_mode,
      bl_mode_i          => t_gen_bl_mode,
      data_mode_i        => t_gen_data_mode,
      mode_load_i        => t_gen_mode_load,
      fixed_bl_i         => t_gen_fixed_bl,
      fixed_instr_i      => t_gen_fixed_instr,
      fixed_addr_i       => t_gen_fixed_addr,
      bram_cmd_i         => (others => '0'),
      bram_valid_i       => '0',
      bram_rdy_o         => open,
      mcb_cmd_en_o       => app_en,
      mcb_cmd_instr_o    => app_cmd(2 downto 0),
      mcb_cmd_addr_o     => app_addr,
      mcb_cmd_bl_o       => open,
      mcb_cmd_full_i     => app_rdy_i,
      mcb_wr_en_o        => app_wdf_wren,
      mcb_wr_data_o      => app_wdf_data(APP_DATA_WIDTH-1 downto 0),
      mcb_wr_full_i      => app_wdf_rdy_i,
      mcb_wr_data_end_o  => app_wdf_end,
      mcb_wr_fifo_counts => tg_wr_fifo_counts,
      mcb_wr_mask_o      => open,
      mcb_rd_en_o        => tg_rd_en,
      mcb_rd_data_i      => app_rd_data(APP_DATA_WIDTH-1 downto 0),
      mcb_rd_empty_i     => not_app_rd_data_valid,
      mcb_rd_fifo_counts => tg_rd_fifo_counts,
      counts_rst         => rst,
      wr_data_counts     => open,
      rd_data_counts     => open,
      cmp_data           => open,
      cmp_error          => open,
      cmp_data_valid     => open,
      error              => error,
      error_status       => open,
      mem_rd_data        => open,
      fixed_data_i       => (others => '0'),
      dq_error_bytelane_cmp => open,
      cumlative_dq_lane_error => open
      );

  manual_clear_error     <= '0';
  

  --***************************************************************************
  -- Reporting the test case status
  --***************************************************************************
  Logging: process
  begin
     wait for 1000 us;
     if (phy_init_done = '1') then
        if (error = '0') then
            report ("****TEST PASSED****");
        else
           report ("****TEST FAILED: DATA ERROR****");
        end if;
     else
        report ("****TEST FAILED: INITIALIZATION DID NOT COMPLETE****");
     end if;
  end process;

end architecture arch_sim_tb_top;

