module ddr3_p0 (
    global_reset_n,
    soft_reset_n,
	csr_soft_reset_req,
	pll_mem_clk,
	pll_write_clk,
	pll_capture0_clk,
	pll_capture1_clk,
	pll_locked,
	afi_reset_n,
	afi_reset_export_n,
	afi_clk,
	afi_half_clk,
	afi_addr,
	afi_ba,
	afi_cke,
	afi_cs_n,
	afi_ras_n,
	afi_we_n,
	afi_cas_n,
	afi_rst_n,
	afi_odt,
	afi_dqs_burst,
	afi_wdata,
	afi_wdata_valid,
	afi_dm,
	afi_rdata,
	afi_rdata_en,
	afi_rdata_en_full,
	afi_rdata_valid,
	afi_cal_success,
	afi_cal_fail,
	afi_wlat,
	afi_rlat,
	afi_mem_clk_disable,
	mem_a,
	mem_ba,
	mem_ck,
	mem_ck_n,
	mem_cke,
	mem_cs_n,
	mem_dm,
	mem_ras_n,
	mem_cas_n,
	mem_we_n,
	mem_dq,
	mem_dqs,
	mem_dqs_n,
	mem_reset_n,
	mem_odt,
	avl_clk,
	avl_reset_n,
	pd_reset_n,
	pd_ack,
	pd_up,
	pd_down,
	phy_clk,
	phy_reset_n,
	phy_read_latency_counter,
	phy_afi_wlat,
	phy_afi_rlat,
	phy_read_increment_vfifo_fr,
	phy_read_increment_vfifo_hr,
	phy_read_increment_vfifo_qr,
	phy_reset_mem_stable,
	phy_write_fr_cycle_shifts,
	phy_cal_debug_info,
	phy_read_fifo_reset,
	phy_vfifo_rd_en_override,
	phy_cal_success,
	phy_cal_fail,
	phy_read_fifo_q,
	calib_skip_steps
);


// ******************************************************************************************************************************** 
// BEGIN PARAMETER SECTION
// All parameters default to "" will have their values passed in from higher level wrapper with the controller and driver. 
parameter DEVICE_FAMILY = "MAX 10";

// choose between abstract (fast) and regular model
`ifndef ALTERA_ALT_MEM_IF_PHY_FAST_SIM_MODEL
  `define ALTERA_ALT_MEM_IF_PHY_FAST_SIM_MODEL 0
`endif

parameter ALTERA_ALT_MEM_IF_PHY_FAST_SIM_MODEL = `ALTERA_ALT_MEM_IF_PHY_FAST_SIM_MODEL;

localparam FAST_SIM_MODEL = ALTERA_ALT_MEM_IF_PHY_FAST_SIM_MODEL;


// On-chip termination
parameter OCT_TERM_CONTROL_WIDTH   = 14;

// PHY-Memory Interface
// Memory device specific parameters, they are set according to the memory spec.
parameter MEM_IF_ADDR_WIDTH			= 15;
parameter MEM_IF_BANKADDR_WIDTH     = 3;
parameter MEM_IF_CK_WIDTH			= 1;
parameter MEM_IF_CLK_EN_WIDTH		= 1;
parameter MEM_IF_CS_WIDTH			= 1;
parameter MEM_IF_DM_WIDTH         	= 2;
parameter MEM_IF_CONTROL_WIDTH    	= 1; 
parameter MEM_IF_DQ_WIDTH         	= 16;
parameter MEM_IF_DQS_WIDTH         	= 2;
parameter MEM_IF_READ_DQS_WIDTH    	= 2;
parameter MEM_IF_WRITE_DQS_WIDTH   	= 2;
parameter MEM_IF_ODT_WIDTH         	= 1;
parameter MEM_IF_NUMBER_OF_RANKS	= 1;

// PHY-Controller (AFI) Interface
// The AFI interface widths are derived from the memory interface widths based on full/half rate operations.
// The calculations are done on higher level wrapper.
parameter AFI_ADDR_WIDTH 	        = 30; 
parameter AFI_DM_WIDTH 	        	= 8; 
parameter AFI_BANKADDR_WIDTH        = 6; 
parameter AFI_CS_WIDTH				= 2;
parameter AFI_CLK_EN_WIDTH          = 2;
parameter AFI_CONTROL_WIDTH         = 2; 
parameter AFI_ODT_WIDTH             = 2; 
parameter AFI_DQ_WIDTH				= 64; 
parameter AFI_WRITE_DQS_WIDTH		= 4;
parameter AFI_RATE_RATIO			= 2;
parameter AFI_WLAT_WIDTH			= 6;
parameter AFI_RLAT_WIDTH			= 6;
parameter AFI_RRANK_WIDTH           = 4;
parameter AFI_WRANK_WIDTH           = 4;

// DLL Interface
parameter DLL_DELAY_CTRL_WIDTH	= 6;

parameter SCC_DATA_WIDTH            = 1;

parameter NUM_SUBGROUP_PER_READ_DQS        = 1;
parameter QVLD_EXTRA_FLOP_STAGES		   = 0;
parameter QVLD_WR_ADDRESS_OFFSET		   = 6;
	
// Read Datapath parameters, the values should not be changed unless the intention is to change the architecture.
// Read valid prediction FIFO
parameter READ_VALID_FIFO_SIZE             = 16;

// Data resynchronization FIFO
parameter READ_FIFO_SIZE                   = 8;

// Latency calibration parameters
parameter MAX_LATENCY_COUNT_WIDTH		   = 5; // calibration finds the best latency by reducing the maximum latency
localparam MAX_READ_LATENCY				   = 2**MAX_LATENCY_COUNT_WIDTH; 

// Write Datapath
// The sequencer uses this value to control write latency during calibration
parameter MAX_WRITE_LATENCY_COUNT_WIDTH = 4;
parameter NUM_WRITE_PATH_FLOP_STAGES    = 1;
parameter NUM_WRITE_FR_CYCLE_SHIFTS = 0;

// Add additional FF stage between core and periphery
parameter REGISTER_C2P = "false";

// Address/Command Datapath
parameter NUM_AC_FR_CYCLE_SHIFTS = 0;

parameter MR1_ODS								= 1;
parameter MR1_RTT								= 3;
parameter MR2_RTT_WR							= 1;
parameter MEM_T_WL								= 6;

localparam MEM_T_RL								= 7;

// The sequencer issues back-to-back reads during calibration, NOPs may need to be inserted depending on the burst length
parameter SEQ_BURST_COUNT_WIDTH = 1;

// The DLL offset control width
parameter DLL_OFFSET_CTRL_WIDTH = 6;

parameter MEM_CLK_FREQ = 300.0;
parameter DELAY_BUFFER_MODE = "HIGH";
parameter DQS_DELAY_CHAIN_PHASE_SETTING = 2;
parameter DQS_PHASE_SHIFT = 9000;
parameter DELAYED_CLOCK_PHASE_SETTING = 2;
parameter AFI_DEBUG_INFO_WIDTH = 32;

parameter CALIB_REG_WIDTH = 8;


parameter TB_PROTOCOL       = "DDR3";
parameter TB_MEM_CLK_FREQ   = "300.0";
parameter TB_RATE           = "HALF";
parameter TB_MEM_DQ_WIDTH   = "16";
parameter TB_MEM_DQS_WIDTH  = "2";
parameter TB_PLL_DLL_MASTER = "true";

parameter FAST_SIM_CALIBRATION = "false";


parameter EXTRA_VFIFO_SHIFT = 0;

localparam SIM_FILESET = ("false" == "true");


// END PARAMETER SECTION
// ******************************************************************************************************************************** 


// ******************************************************************************************************************************** 
// BEGIN PORT SECTION


// When the PHY is selected to be a PLL/DLL SLAVE, the PLL and DLL are instantied at the top level of the example design
input	pll_mem_clk;	
input	pll_write_clk;
input	pll_capture0_clk;
input	pll_capture1_clk;
input	pll_locked;






// Reset Interface, AFI 2.0
input   global_reset_n;		// Resets (active-low) the whole system (all PHY logic + PLL)
input	soft_reset_n;		// Resets (active-low) PHY logic only, PLL is NOT reset
output	afi_reset_export_n;	// Asynchronously asserted and synchronously de-asserted on afi_clk domain
output	afi_reset_n;		// Asynchronously asserted and synchronously de-asserted on afi_clk domain
							// should be used to reset system level afi_clk domain logic
input csr_soft_reset_req;  // Reset request (active_high) being driven by external debug master

// OCT termination control signals

// PHY-Controller Interface, AFI 2.0
// Control Interface
input   [AFI_ADDR_WIDTH-1:0]        afi_addr;		// address
input   [AFI_BANKADDR_WIDTH-1:0]    afi_ba;			// bank
input   [AFI_CLK_EN_WIDTH-1:0]      afi_cke;		// clock enable
input   [AFI_CS_WIDTH-1:0]          afi_cs_n;		// chip select
input   [AFI_CONTROL_WIDTH-1:0]     afi_ras_n;
input   [AFI_CONTROL_WIDTH-1:0]     afi_we_n;
input   [AFI_CONTROL_WIDTH-1:0]     afi_cas_n;
input   [AFI_ODT_WIDTH-1:0]         afi_odt;
input   [AFI_CONTROL_WIDTH-1:0]     afi_rst_n;


// Write data interface
input   [AFI_WRITE_DQS_WIDTH-1:0]   afi_dqs_burst;
input   [AFI_DQ_WIDTH-1:0]          afi_wdata;			// write data
input	[AFI_WRITE_DQS_WIDTH-1:0]	afi_wdata_valid;	// write data valid, used to maintain write latency required by protocol spec
input   [AFI_DM_WIDTH-1:0]          afi_dm;				// write data mask

// Read data interface
output  [AFI_DQ_WIDTH-1:0]    afi_rdata;           // read data				
input   [AFI_RATE_RATIO-1:0]  afi_rdata_en;        // read enable, used to maintain the read latency calibrated by PHY
input   [AFI_RATE_RATIO-1:0]  afi_rdata_en_full;   // read enable full burst, used to create DQS enable
output  [AFI_RATE_RATIO-1:0]  afi_rdata_valid;     // read data valid


// Status interface
output  afi_cal_success;	// calibration success
output  afi_cal_fail;		// calibration failure

output [AFI_WLAT_WIDTH-1:0]			afi_wlat;
output [AFI_RLAT_WIDTH-1:0]			afi_rlat;
input  [MEM_IF_CK_WIDTH-1:0] afi_mem_clk_disable;


// Ping Pong PHY signals

// PHY-Memory Interface

output  [MEM_IF_ADDR_WIDTH-1:0]       mem_a;        // address
output  [MEM_IF_BANKADDR_WIDTH-1:0]   mem_ba;       // bank
inout   [MEM_IF_CK_WIDTH-1:0]         mem_ck;       // differential address and command clock
inout   [MEM_IF_CK_WIDTH-1:0]         mem_ck_n;
output  [MEM_IF_CLK_EN_WIDTH-1:0]     mem_cke;      // clock enable
output  [MEM_IF_CS_WIDTH-1:0]         mem_cs_n;     // chip select
output  [MEM_IF_DM_WIDTH-1:0]         mem_dm;       // data mask
output  [MEM_IF_CONTROL_WIDTH-1:0]    mem_ras_n;		
output  [MEM_IF_CONTROL_WIDTH-1:0]    mem_cas_n;		
output  [MEM_IF_CONTROL_WIDTH-1:0]    mem_we_n;		
inout	[MEM_IF_DQ_WIDTH-1:0]         mem_dq;       // bidirectional data bus
inout	[MEM_IF_DQS_WIDTH-1:0]        mem_dqs;      // bidirectional data strobe
inout	[MEM_IF_DQS_WIDTH-1:0]        mem_dqs_n;    // differential bidirectional data strobe
output  [MEM_IF_ODT_WIDTH-1:0]        mem_odt;
output	                              mem_reset_n;

// PLL Interface
input	afi_clk;
input	afi_half_clk;




output  avl_clk;
output  avl_reset_n;
input  pd_reset_n;
input  pd_ack;
output pd_up;
output pd_down;

output  phy_clk;
output  phy_reset_n;

input  [MAX_LATENCY_COUNT_WIDTH-1:0]  phy_read_latency_counter;
input           [AFI_WLAT_WIDTH-1:0]  phy_afi_wlat;
input           [AFI_RLAT_WIDTH-1:0]  phy_afi_rlat;
input    [MEM_IF_READ_DQS_WIDTH-1:0]  phy_read_increment_vfifo_fr;
input    [MEM_IF_READ_DQS_WIDTH-1:0]  phy_read_increment_vfifo_hr;
input    [MEM_IF_READ_DQS_WIDTH-1:0]  phy_read_increment_vfifo_qr;
input                                 phy_reset_mem_stable;
input	[MEM_IF_WRITE_DQS_WIDTH*2-1:0] phy_write_fr_cycle_shifts;
input   [AFI_DEBUG_INFO_WIDTH - 1:0]  phy_cal_debug_info;
input    [MEM_IF_READ_DQS_WIDTH-1:0]  phy_read_fifo_reset;
input    [MEM_IF_READ_DQS_WIDTH-1:0]  phy_vfifo_rd_en_override;
input                                 phy_cal_success;	// calibration success
input                                 phy_cal_fail;		// calibration failure
output            [AFI_DQ_WIDTH-1:0]  phy_read_fifo_q; 

output         [CALIB_REG_WIDTH-1:0]  calib_skip_steps;


// END PORT SECTION


initial $display("Using %0s core emif simulation models", FAST_SIM_MODEL ? "Fast" : "Regular");


assign afi_cal_success = phy_cal_success;
assign afi_cal_fail = phy_cal_fail;

assign avl_clk = afi_clk;
assign avl_reset_n = afi_reset_n; 


integer MEM_T_WL_int = (MEM_T_WL/2);
assign afi_wlat = MEM_T_WL_int[AFI_WLAT_WIDTH-1:0];


// Exporting read latency is currently not supported
assign afi_rlat = 0;


ddr3_p0_memphy_m10 #(
	.DEVICE_FAMILY(DEVICE_FAMILY),
	.MEM_ADDRESS_WIDTH(MEM_IF_ADDR_WIDTH),
	.MEM_BANK_WIDTH(MEM_IF_BANKADDR_WIDTH),
	.MEM_CLK_EN_WIDTH(MEM_IF_CLK_EN_WIDTH),
	.MEM_CK_WIDTH(MEM_IF_CK_WIDTH),
	.MEM_ODT_WIDTH(MEM_IF_ODT_WIDTH),
	.MEM_DQS_WIDTH(MEM_IF_DQS_WIDTH),
	.MEM_CHIP_SELECT_WIDTH(MEM_IF_CS_WIDTH),
	.MEM_DM_WIDTH(MEM_IF_DM_WIDTH),
	.MEM_CONTROL_WIDTH(MEM_IF_CONTROL_WIDTH),
	.MEM_DQ_WIDTH(MEM_IF_DQ_WIDTH),
	.MEM_READ_DQS_WIDTH(MEM_IF_READ_DQS_WIDTH),
	.MEM_WRITE_DQS_WIDTH(MEM_IF_WRITE_DQS_WIDTH),
	.AFI_ADDRESS_WIDTH(AFI_ADDR_WIDTH),
	.AFI_BANK_WIDTH(AFI_BANKADDR_WIDTH),
	.AFI_CHIP_SELECT_WIDTH(AFI_CS_WIDTH),
	.AFI_CLK_EN_WIDTH(AFI_CLK_EN_WIDTH),
	.AFI_ODT_WIDTH(AFI_ODT_WIDTH),
	.AFI_DATA_MASK_WIDTH(AFI_DM_WIDTH),
	.AFI_DQS_WIDTH(AFI_WRITE_DQS_WIDTH),
	.AFI_CONTROL_WIDTH(AFI_CONTROL_WIDTH),
	.AFI_DATA_WIDTH(AFI_DQ_WIDTH),
	.AFI_RATE_RATIO(AFI_RATE_RATIO),
	.MEM_T_RL(MEM_T_RL),
	.MAX_LATENCY_COUNT_WIDTH(MAX_LATENCY_COUNT_WIDTH),
	.NUM_WRITE_PATH_FLOP_STAGES(NUM_WRITE_PATH_FLOP_STAGES),
	.NUM_WRITE_FR_CYCLE_SHIFTS(NUM_WRITE_FR_CYCLE_SHIFTS),
	.NUM_AC_FR_CYCLE_SHIFTS(NUM_AC_FR_CYCLE_SHIFTS),
	.CALIB_REG_WIDTH(CALIB_REG_WIDTH),
	.AFI_DEBUG_INFO_WIDTH(AFI_DEBUG_INFO_WIDTH)
) umemphy (
	.global_reset_n(global_reset_n),
	.soft_reset_n(soft_reset_n & ~csr_soft_reset_req),
	.ctl_reset_n(afi_reset_n),
	.ctl_reset_export_n(afi_reset_export_n),
	.pll_locked(pll_locked),
	.afi_addr(afi_addr),
	.afi_ba(afi_ba),
	.afi_cke(afi_cke),
	.afi_cs_n(afi_cs_n),
	.afi_ras_n(afi_ras_n),
	.afi_we_n(afi_we_n),
	.afi_cas_n(afi_cas_n),
	.afi_rst_n(afi_rst_n),
	.afi_mem_clk_disable(afi_mem_clk_disable),
	.afi_odt(afi_odt),
	.afi_dqs_burst(afi_dqs_burst),
	.afi_wdata(afi_wdata),
	.afi_wdata_valid(afi_wdata_valid),
	.afi_dm(afi_dm),
	.afi_rdata(afi_rdata),
	.afi_rdata_en(afi_rdata_en),
	.afi_rdata_valid(afi_rdata_valid),
	.afi_cal_success(afi_cal_success),
	.afi_cal_fail(afi_cal_fail),
	.mem_a(mem_a),
	.mem_ba(mem_ba),
	.mem_ck(mem_ck),
	.mem_ck_n(mem_ck_n),
	.mem_cke(mem_cke),
	.mem_cs_n(mem_cs_n),
	.mem_dm(mem_dm),
	.mem_ras_n(mem_ras_n),
	.mem_cas_n(mem_cas_n),
	.mem_we_n(mem_we_n),
	.mem_reset_n(mem_reset_n),
	.mem_dq(mem_dq),
	.mem_dqs(mem_dqs),
	.mem_dqs_n(mem_dqs_n),
	.mem_odt(mem_odt),
	.pll_afi_clk(afi_clk),
	.pll_mem_clk(pll_mem_clk),
	.pll_write_clk(pll_write_clk),
	.pll_capture0_clk(pll_capture0_clk),
	.pll_capture1_clk(pll_capture1_clk),
	.phy_read_latency_counter(phy_read_latency_counter),
	.phy_read_increment_vfifo_hr(phy_read_increment_vfifo_hr),
	.phy_cal_debug_info(phy_cal_debug_info),
	.phy_read_fifo_reset(phy_read_fifo_reset),
	.phy_vfifo_rd_en_override(phy_vfifo_rd_en_override),
	.calib_skip_steps(calib_skip_steps),
	.phy_clk(phy_clk),
	.phy_reset_n(phy_reset_n),
	.pd_reset_n(pd_reset_n),
	.pd_ack(pd_ack),
	.pd_up(pd_up),
	.pd_down(pd_down)
);

endmodule