diff --git a/src/ddr2.ucf b/src/ddr2.ucf new file mode 100644 index 0000000..a08dab8 --- /dev/null +++ b/src/ddr2.ucf @@ -0,0 +1,269 @@ +NET ddr2_a[0] LOC="L30"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[1] LOC="M30"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[2] LOC="N29"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[3] LOC="P29"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[4] LOC="K31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[5] LOC="L31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[6] LOC="P31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[7] LOC="P30"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[8] LOC="M31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[9] LOC="R28"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[10] LOC="J31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[11] LOC="R29"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_a[12] LOC="T31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +#NET ddr2_a[13] LOC="H29"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_ba[0] LOC="G31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_ba[1] LOC="J30"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +#NET ddr2_ba[2] LOC="R31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_cas_n LOC="E31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_cke LOC="T28"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_ck_n[0] LOC="AJ29"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_ck[0] LOC="AK29"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_ck_n[1] LOC="F28"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_ck[1] LOC="E28"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_cs_n LOC="L29"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[0] LOC="AF30"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[1] LOC="AK31"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[2] LOC="AF31"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[3] LOC="AD30"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[4] LOC="AJ30"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[5] LOC="AF29"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[6] LOC="AD29"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[7] LOC="AE29"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[8] LOC="AH27"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[9] LOC="AF28"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[10] LOC="AH28"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[11] LOC="AA28"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[12] LOC="AG25"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[13] LOC="AJ26"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[14] LOC="AG28"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[15] LOC="AB28"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[16] LOC="AC28"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[17] LOC="AB25"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[18] LOC="AC27"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[19] LOC="AA26"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[20] LOC="AB26"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[21] LOC="AA24"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[22] LOC="AB27"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[23] LOC="AA25"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[24] LOC="AC29"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[25] LOC="AB30"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[26] LOC="W31"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[27] LOC="V30"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[28] LOC="AC30"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[29] LOC="W29"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[30] LOC="V27"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[31] LOC="W27"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[32] LOC="V29"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[33] LOC="Y27"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[34] LOC="Y26"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[35] LOC="W24"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[36] LOC="V28"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[37] LOC="W25"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[38] LOC="W26"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[39] LOC="V24"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[40] LOC="R24"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[41] LOC="P25"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[42] LOC="N24"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[43] LOC="P26"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[44] LOC="T24"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[45] LOC="N25"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[46] LOC="P27"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[47] LOC="N28"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[48] LOC="M28"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[49] LOC="L28"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[50] LOC="F25"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[51] LOC="H25"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[52] LOC="K27"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[53] LOC="K28"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[54] LOC="H24"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[55] LOC="G26"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[56] LOC="G25"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[57] LOC="M26"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[58] LOC="J24"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[59] LOC="L26"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[60] LOC="J27"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[61] LOC="M25"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[62] LOC="L25"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dq[63] LOC="L24"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dm[0] LOC="AJ31"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dm[1] LOC="AE28"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dm[2] LOC="Y24"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dm[3] LOC="Y31"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dm[4] LOC="V25"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dm[5] LOC="P24"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dm[6] LOC="F26"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dm[7] LOC="J25"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs_n[0] LOC="AA30"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs[0] LOC="AA29"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs_n[1] LOC="AK27"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs[1] LOC="AK28"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs_n[2] LOC="AJ27"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs[2] LOC="AK26"; # Bank 21, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs_n[3] LOC="AA31"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs[3] LOC="AB31"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs_n[4] LOC="Y29"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs[4] LOC="Y28"; # Bank 17, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs_n[5] LOC="E27"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs[5] LOC="E26"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs_n[6] LOC="G28"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs[6] LOC="H28"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs_n[7] LOC="H27"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_dqs[7] LOC="G27"; # Bank 19, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_odt LOC="F31"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_ras_n LOC="H30"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors +NET ddr2_we_n LOC="K29"; # Bank 15, Vcco=1.8V, DCI using 49.9 ohm resistors + + +NET "ddr2_dq[*]" IOSTANDARD = SSTL18_II_DCI; +NET "ddr2_a[*]" IOSTANDARD = SSTL18_II; +NET "ddr2_ba[*]" IOSTANDARD = SSTL18_II; +NET "ddr2_ras_n" IOSTANDARD = SSTL18_II; +NET "ddr2_cas_n" IOSTANDARD = SSTL18_II; +NET "ddr2_we_n" IOSTANDARD = SSTL18_II; +NET "ddr2_cs_n" IOSTANDARD = SSTL18_II; +NET "ddr2_odt" IOSTANDARD = SSTL18_II; +NET "ddr2_cke" IOSTANDARD = SSTL18_II; +NET "ddr2_dm[*]" IOSTANDARD = SSTL18_II_DCI; +NET "ddr2_dqs[*]" IOSTANDARD = DIFF_SSTL18_II_DCI; +NET "ddr2_dqs_n[*]" IOSTANDARD = DIFF_SSTL18_II_DCI; +NET "ddr2_ck[*]" IOSTANDARD = DIFF_SSTL18_II; +NET "ddr2_ck_n[*]" IOSTANDARD = DIFF_SSTL18_II; + + + +################################################################################ +# Copied from ddr2_controller # +################################################################################ + + +############################################################################### +# Define multicycle paths - these paths may take longer because additional +# time allowed for logic to settle in calibration/initialization FSM +############################################################################### + +# MIG 2.1: Eliminate Timegroup definitions for CLK0, and CLK90. Instead trace +# multicycle paths from originating flip-flop to ANY destination +# flip-flop (or in some cases, it can also be a BRAM) +# MUX Select for either rising/falling CLK0 for 2nd stage read capture +INST "*/u_phy_calib/gen_rd_data_sel*.u_ff_rd_data_sel" TNM = "TNM_RD_DATA_SEL"; +TIMESPEC "TS_MC_RD_DATA_SEL" = FROM "TNM_RD_DATA_SEL" TO FFS +"TS_CLK_200" * 4; +# MUX select for read data - optional delay on data to account for byte skews +INST "*/u_usr_rd/gen_rden_sel_mux*.u_ff_rden_sel_mux" TNM = "TNM_RDEN_SEL_MUX"; +TIMESPEC "TS_MC_RDEN_SEL_MUX" = FROM "TNM_RDEN_SEL_MUX" TO FFS +"TS_CLK_200" * 4; +# Calibration/Initialization complete status flag (for PHY logic only) - can +# be used to drive both flip-flops and BRAMs +INST "*/u_phy_init/u_ff_phy_init_data_sel" TNM = "TNM_PHY_INIT_DATA_SEL"; +TIMESPEC "TS_MC_PHY_INIT_DATA_SEL_0" = FROM "TNM_PHY_INIT_DATA_SEL" TO FFS +"TS_CLK_200" * 4; +# The RAM path is only used in cases where Write Latency (Additive Latency + +# (CAS Latency - 1) + (1 in case of RDIMM)) is 2 or below. So these constraints are +# valid for CAS Latency = 3, Additive Latency = 0 and selected part is not RDIMM. +# If Write Latency is higher than 3, then a warning will appear in PAR, +# and the constraint can be ignored as this path does not exist. RAM constraint +# can be safely removed if the warning is not to be displayed. +TIMESPEC "TS_MC_PHY_INIT_DATA_SEL_90" = FROM "TNM_PHY_INIT_DATA_SEL" TO RAMS +"TS_CLK_200" * 4; +# Select (address) bits for SRL32 shift registers used in stage3/stage4 +# calibration +INST "*/u_phy_calib/gen_gate_dly*.u_ff_gate_dly" TNM = "TNM_GATE_DLY"; +TIMESPEC "TS_MC_GATE_DLY" = FROM "TNM_GATE_DLY" TO FFS "TS_CLK_200" * 4; + +INST "*/u_phy_calib/gen_rden_dly*.u_ff_rden_dly" TNM = "TNM_RDEN_DLY"; +TIMESPEC "TS_MC_RDEN_DLY" = FROM "TNM_RDEN_DLY" TO FFS "TS_CLK_200" * 4; + +INST "*/u_phy_calib/gen_cal_rden_dly*.u_ff_cal_rden_dly" + TNM = "TNM_CAL_RDEN_DLY"; +TIMESPEC "TS_MC_CAL_RDEN_DLY" = FROM "TNM_CAL_RDEN_DLY" TO FFS +"TS_CLK_200" * 4; +############################################################################### +#The following constraint is added to prevent (false) hold time violations on +#the data path from stage1 to stage2 capture flops. Stage1 flops are clocked by +#the delayed DQS and stage2 flops are clocked by the clk0 clock. Placing a TIG +#on the DQ IDDR capture flop instance to achieve this is acceptable because timing +#is guaranteed through the use of separate Predictable IP constraints. These +#violations are reported when anunconstrained path report is run. +############################################################################### +INST "*/gen_dq[*].u_iob_dq/gen*.u_iddr_dq" TIG ; +############################################################################### +# DQS Read Post amble Glitch Squelch circuit related constraints +############################################################################### + +############################################################################### +# LOC placement of DQS-squelch related IDDR and IDELAY elements +# Each circuit can be located at any of the following locations: +# 1. Unused "N"-side of DQS differential pair I/O +# 2. DM data mask (output only, input side is free for use) +# 3. Any output-only site +############################################################################### + +############################################################################### +#The following constraint is added to avoid the HOLD violations in the trace report +#when run for unconstrained paths.These two FF groups will be clocked by two different +# clocks and hence there should be no timing analysis performed on this path. +############################################################################### +INST "*/u_mem_if_top/u_phy_top/u_phy_io/u_phy_calib/gen_gate[*].u_en_dqs_ff" TNM = EN_DQS_FF; +TIMESPEC TS_FROM_EN_DQS_FF_TO_DQ_CE_FF = FROM EN_DQS_FF TO TNM_DQ_CE_IDDR 3.85 ns DATAPATHONLY; + +INST "*/gen_dqs[0].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y96"; +INST "*/gen_dqs[0].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y96"; +INST "*/gen_dqs[1].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y58"; +INST "*/gen_dqs[1].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y58"; +INST "*/gen_dqs[2].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y62"; +INST "*/gen_dqs[2].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y62"; +INST "*/gen_dqs[3].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y100"; +INST "*/gen_dqs[3].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y100"; +INST "*/gen_dqs[4].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y102"; +INST "*/gen_dqs[4].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y102"; +INST "*/gen_dqs[5].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y256"; +INST "*/gen_dqs[5].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y256"; +INST "*/gen_dqs[6].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y260"; +INST "*/gen_dqs[6].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y260"; +INST "*/gen_dqs[7].u_iob_dqs/u_iddr_dq_ce" LOC = "ILOGIC_X0Y262"; +INST "*/gen_dqs[7].u_iob_dqs/u_iodelay_dq_ce" LOC = "IODELAY_X0Y262"; + +############################################################################### +# LOC and timing constraints for flop driving DQS CE enable signal +# from fabric logic. Even though the absolute delay on this path is +# calibrated out (when synchronizing this output to DQS), the delay +# should still be kept as low as possible to reduce post-calibration +# voltage/temp variations - these are roughly proportional to the +# absolute delay of the path. +# The following code has been commented for V5 as the predictable IP will take +# care of placement of these flops by meeting the MAXDELAY requirement. +# These constraints will be removed in the next release. +############################################################################### + +INST "*/u_phy_calib/gen_gate[0].u_en_dqs_ff" LOC = SLICE_X0Y48; +INST "*/u_phy_calib/gen_gate[1].u_en_dqs_ff" LOC = SLICE_X0Y29; +INST "*/u_phy_calib/gen_gate[2].u_en_dqs_ff" LOC = SLICE_X0Y31; +INST "*/u_phy_calib/gen_gate[3].u_en_dqs_ff" LOC = SLICE_X0Y50; +INST "*/u_phy_calib/gen_gate[4].u_en_dqs_ff" LOC = SLICE_X0Y51; +INST "*/u_phy_calib/gen_gate[5].u_en_dqs_ff" LOC = SLICE_X0Y128; +INST "*/u_phy_calib/gen_gate[6].u_en_dqs_ff" LOC = SLICE_X0Y130; +INST "*/u_phy_calib/gen_gate[7].u_en_dqs_ff" LOC = SLICE_X0Y131; + +# Control for DQS gate - from fabric flop. Prevent "runaway" delay - +# two parts to this path: (1) from fabric flop to IDELAY, (2) from +# IDELAY to asynchronous reset of IDDR that drives the DQ CE's +# This can be relaxed by the user for lower frequencies: +# 300MHz = 850ps, 267MHz = 900ps. At 200MHz = 950ps. +# In general PAR should be able to route this +# within 900ps over all speed grades. +NET "*/u_phy_io/en_dqs[*]" MAXDELAY = 600 ps; +NET "*/u_phy_io/gen_dqs*.u_iob_dqs/en_dqs_sync" MAXDELAY = 850 ps; + +############################################################################### +# "Half-cycle" path constraint from IOB flip-flop to CE pin for all DQ IDDR's +# for DQS Read Post amble Glitch Squelch circuit +############################################################################### + +# Max delay from output of IOB flip-flop to CE input of DQ IDDRs = +# tRPST + some slack where slack account for rise-time of DQS on board. +# For now assume slack = 0.400ns (based on initial SPICE simulations, +# assumes use of ODT), so time = 0.4*Tcyc + 0.40ns = 1.6ns @333MHz +INST "*/gen_dqs[*].u_iob_dqs/u_iddr_dq_ce" TNM = "TNM_DQ_CE_IDDR"; +INST "*/gen_dq[*].u_iob_dq/gen_stg2_*.u_iddr_dq" TNM = "TNM_DQS_FLOPS"; +TIMESPEC "TS_DQ_CE" = FROM "TNM_DQ_CE_IDDR" TO "TNM_DQS_FLOPS" 2.4 ns; diff --git a/src/memory_controller.vhd b/src/memory_controller.vhd new file mode 100644 index 0000000..cf6b9db --- /dev/null +++ b/src/memory_controller.vhd @@ -0,0 +1,241 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity memory_controller is + port ( + -- clocks + sys_clk0: in std_logic; + sys_clk90: in std_logic; + sys_clkdiv0: in std_logic; + sys_clk_locked: in std_logic; + sys_clk_idelay: in std_logic; + sys_reset: in std_logic; + + -- read and write requests + request_addr: in std_logic_vector(27 downto 0); -- 256 MiB, no CS (SR) + request_type: in std_logic; -- read (1) or write (0) + request_data: in std_logic_vector(255 downto 0); + request_mask: in std_logic_vector(31 downto 0); + request_valid: in std_logic; + request_ready: out std_logic; + + -- read responses + response_data: out std_logic_vector(255 downto 0); + response_valid: out std_logic; -- only asserted for one cycle, no ready + + -- physical ddr2 interface + ddr2_dq: inout std_logic_vector(63 downto 0); + ddr2_a: out std_logic_vector(12 downto 0); + ddr2_ba: out std_logic_vector(1 downto 0); + ddr2_ras_n: out std_logic; + ddr2_cas_n: out std_logic; + ddr2_we_n: out std_logic; + ddr2_cs_n: out std_logic_vector(0 downto 0); + ddr2_odt: out std_logic_vector(0 downto 0); + ddr2_cke: out std_logic_vector(0 downto 0); + ddr2_dm: out std_logic_vector(7 downto 0); + ddr2_dqs: inout std_logic_vector(7 downto 0); + ddr2_dqs_n: inout std_logic_vector(7 downto 0); + ddr2_ck: out std_logic_vector(1 downto 0); + ddr2_ck_n: out std_logic_vector(1 downto 0) + ); +end memory_controller; + +architecture rtl of memory_controller is + + signal clk: std_logic; + signal reset_p: std_logic; + + type request_states is ( + REQ_IDLE, + REQ_WRITE + ); + signal request_state: request_states := REQ_IDLE; + + type response_states is ( + RES_IDLE, + RES_WAIT_SECOND + ); + signal response_state: response_states := RES_IDLE; + + signal ram_init_done: std_logic; + + signal ram_address: std_logic_vector(30 downto 0); + signal ram_command: std_logic_vector(2 downto 0); + signal ram_data_in: std_logic_vector(127 downto 0); + signal ram_mask_in: std_logic_vector(15 downto 0); + signal ram_data_out: std_logic_vector(127 downto 0); + signal ram_enq_address: std_logic; + signal ram_enq_data: std_logic; + signal ram_address_afull: std_logic; + signal ram_data_afull: std_logic; + signal ram_data_valid: std_logic; + + signal is_request_ready: std_logic; + + signal data_in_high: std_logic_vector(127 downto 0); + signal mask_in_high: std_logic_vector(15 downto 0); + signal data_out_low: std_logic_vector(127 downto 0); + +begin + + reset_p <= not sys_reset; + + -- the lowest three bits pick one of the 8 bytes inside the 64b ram width + ram_address <= "000000" & request_addr(27 downto 3); + -- WRITE is 000 and READ is 001 + ram_command <= "00" & request_type; + -- we directly pass the lower half to the mig fifo and only store the + -- upper half for writing on a second cycle (this works because we can + -- still write 12 words to the fifo when the *almost full* signal is + -- asserted by the mig) + ram_data_in <= request_data(127 downto 0) when request_state = REQ_IDLE else + data_in_high; + ram_mask_in <= request_mask(15 downto 0) when request_state = REQ_IDLE else + mask_in_high; + -- to directly pass data to the fifos (see above) we also have to enable + -- the fifo write signals combinatorially, otherwise we miss the first part + ram_enq_address <= is_request_ready and request_valid; + -- the data write signal is only high for write requests and also has to + -- be kept high for a second cycle to write the upper half of the data + ram_enq_data <= '1' when ( (is_request_ready and request_valid) = '1' and + (request_type = '0') + ) or (request_state = REQ_WRITE) + else '0'; + -- we are only ready if we can write to *both* fifos and everything is + -- fully initialized (we could theoretically only look at the address fifo + -- for read requests) + is_request_ready <= '1' when (ram_init_done = '1') and + (ram_address_afull = '0') and + (ram_data_afull = '0') and + (request_state = REQ_IDLE) + else '0'; + request_ready <= is_request_ready; + + input: process(clk, sys_reset) + begin + if sys_reset = '1' then + request_state <= REQ_IDLE; + elsif rising_edge(clk) then + case request_state is + when REQ_IDLE => + if is_request_ready = '1' and request_valid = '1' then + if request_type = '1' then -- READ + request_state <= REQ_IDLE; + else -- WRITE + data_in_high <= request_data(255 downto 128); + mask_in_high <= request_mask(31 downto 16); + request_state <= REQ_WRITE; + end if; + end if; + when REQ_WRITE => + request_state <= REQ_IDLE; + end case; + end if; + end process input; + + + -- we pass the higher half directly from the mig + response_data <= ram_data_out & data_out_low; + -- read_valid only asserted for one cycle, must be read immediately + response_valid <= '1' when (response_state = RES_WAIT_SECOND) and + (ram_data_valid = '1') + else '0'; + + output: process(clk, sys_reset) + begin + if sys_reset = '1' then + response_state <= RES_IDLE; + elsif rising_edge(clk) then + case response_state is + when RES_IDLE => + if ram_data_valid = '1' then + data_out_low <= ram_data_out; + response_state <= RES_WAIT_SECOND; + end if; + when RES_WAIT_SECOND => + if ram_data_valid = '1' then + response_state <= RES_IDLE; + end if; + end case; + end if; + end process output; + + ddr2_controller: entity work.ddr2_controller port map ( + clk0 => sys_clk0, + clk90 => sys_clk90, + clkdiv0 => sys_clkdiv0, + clk200 => sys_clk_idelay, + locked => sys_clk_locked, + sys_rst_n => reset_p, + rst0_tb => open, + clk0_tb => clk, + phy_init_done => ram_init_done, + app_wdf_afull => ram_data_afull, + app_af_afull => ram_address_afull, + rd_data_valid => ram_data_valid, + app_wdf_wren => ram_enq_data, + app_af_wren => ram_enq_address, + app_af_addr => ram_address, + app_af_cmd => ram_command, + rd_data_fifo_out => ram_data_out, + app_wdf_data => ram_data_in, + app_wdf_mask_data => ram_mask_in, + ddr2_dq => ddr2_dq, + ddr2_a => ddr2_a, + ddr2_ba => ddr2_ba, + ddr2_ras_n => ddr2_ras_n, + ddr2_cas_n => ddr2_cas_n, + ddr2_we_n => ddr2_we_n, + ddr2_cs_n => ddr2_cs_n, + ddr2_odt => ddr2_odt, + ddr2_cke => ddr2_cke, + ddr2_dm => ddr2_dm, + ddr2_dqs => ddr2_dqs, + ddr2_dqs_n => ddr2_dqs_n, + ddr2_ck => ddr2_ck, + ddr2_ck_n => ddr2_ck_n + ); + + --~ sys_clk_p : in std_logic; + --~ sys_clk_n : in std_logic; + --~ clk200_p : in std_logic; + --~ clk200_n : in std_logic; + --~ sys_rst_n : in std_logic; + + --~ rst0_tb : out std_logic; + --~ clk0_tb : out std_logic; + + --~ phy_init_done : out std_logic; + + --~ app_wdf_afull : out std_logic; + --~ app_af_afull : out std_logic; + --~ app_wdf_wren : in std_logic; + --~ app_af_wren : in std_logic; + --~ app_af_addr : in std_logic_vector(30 downto 0); + --~ app_af_cmd : in std_logic_vector(2 downto 0); + --~ app_wdf_data : in std_logic_vector(127 downto 0); + --~ app_wdf_mask_data : in std_logic_vector(15 downto 0); + --~ rd_data_fifo_out : out std_logic_vector(127 downto 0); + --~ rd_data_valid : out std_logic; + + --~ ddr2_dq : inout std_logic_vector(63 downto 0); + --~ ddr2_a : out std_logic_vector(12 downto 0); + --~ ddr2_ba : out std_logic_vector(1 downto 0); + --~ ddr2_ras_n : out std_logic; + --~ ddr2_cas_n : out std_logic; + --~ ddr2_we_n : out std_logic; + --~ ddr2_cs_n : out std_logic_vector(0 downto 0); + --~ ddr2_odt : out std_logic_vector(0 downto 0); + --~ ddr2_cke : out std_logic_vector(0 downto 0); + --~ ddr2_dm : out std_logic_vector(7 downto 0); + --~ ddr2_dqs : inout std_logic_vector(7 downto 0); + --~ ddr2_dqs_n : inout std_logic_vector(7 downto 0); + --~ ddr2_ck : out std_logic_vector(1 downto 0); + --~ ddr2_ck_n : out std_logic_vector(1 downto 0) + +end rtl; +