URL
https://opencores.org/ocsvn/genesys_ddr2/genesys_ddr2/trunk
Subversion Repositories genesys_ddr2
Compare Revisions
- This comparison shows the changes necessary to convert path
/genesys_ddr2/trunk
- from Rev 2 to Rev 3
- ↔ Reverse comparison
Rev 2 → Rev 3
/bench/Xilinx_MIG_bench/sim/ddr2_tb_test_gen.v
File deleted
/bench/Xilinx_MIG_bench/sim/ddr2_user_if_top.v
File deleted
/bench/Xilinx_MIG_bench/sim/ddr2_tb_test_cmp.v
File deleted
/bench/Xilinx_MIG_bench/sim/ddr2_tb_test_data_gen.v
File deleted
/bench/Xilinx_MIG_bench/sim/ddr2_tb_test_addr_gen.v
File deleted
/bench/Xilinx_MIG_bench/sim/ddr2_tb_top.v
File deleted
/bench/Xilinx_MIG_bench/sim/ddr2_adr_data_gen.v
File deleted
bench/Xilinx_MIG_bench/sim
Property changes :
Deleted: bugtraq:number
## -1 +0,0 ##
-true
\ No newline at end of property
Index: bench/Xilinx_MIG_bench
===================================================================
--- bench/Xilinx_MIG_bench (revision 2)
+++ bench/Xilinx_MIG_bench (nonexistent)
bench/Xilinx_MIG_bench
Property changes :
Deleted: bugtraq:number
## -1 +0,0 ##
-true
\ No newline at end of property
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_chipscope.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_chipscope.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_chipscope.v (nonexistent)
@@ -1,114 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_chipscope.v
-// /___/ /\ Date Last Modified: $Data$
-// \ \ / \ Date Created: 9/14/06
-// \___\/\___\
-//
-//Device: Virtex-5
-//Purpose:
-// Skeleton Chipscope module declarations - for simulation only
-//Reference:
-//Revision History:
-//
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module icon4
- (
- control0,
- control1,
- control2,
- control3
- )
- /* synthesis syn_black_box syn_noprune = 1 */;
- output [35:0] control0;
- output [35:0] control1;
- output [35:0] control2;
- output [35:0] control3;
-endmodule
-
-module vio_async_in192
- (
- control,
- async_in
- )
- /* synthesis syn_black_box syn_noprune = 1 */;
- input [35:0] control;
- input [191:0] async_in;
-endmodule
-
-module vio_async_in96
- (
- control,
- async_in
- )
- /* synthesis syn_black_box syn_noprune = 1 */;
- input [35:0] control;
- input [95:0] async_in;
-endmodule
-
-module vio_async_in100
- (
- control,
- async_in
- )
- /* synthesis syn_black_box syn_noprune = 1 */;
- input [35:0] control;
- input [99:0] async_in;
-endmodule
-
-module vio_sync_out32
- (
- control,
- clk,
- sync_out
- )
- /* synthesis syn_black_box syn_noprune = 1 */;
- input [35:0] control;
- input clk;
- output [31:0] sync_out;
-endmodule
\ No newline at end of file
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_dq_iob.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_dq_iob.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_dq_iob.v (nonexistent)
@@ -1,592 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_phy_dq_iob.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module places the data in the IOBs.
-//Reference:
-//Revision History:
-// Rev 1.1 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
-// Rev 1.2 - DIRT strings removed and modified the code. PK. 11/13/08
-// Rev 1.3 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
-// on IODELAY primitive. PK. 11/27/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_phy_dq_iob #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter HIGH_PERFORMANCE_MODE = "TRUE",
- parameter IODELAY_GRP = "IODELAY_MIG",
- parameter FPGA_SPEED_GRADE = 2
- )
- (
- input clk0,
- input clk90,
- input clkdiv0,
- input rst90,
- input dlyinc,
- input dlyce,
- input dlyrst,
- input [1:0] dq_oe_n,
- input dqs,
- input ce,
- input rd_data_sel,
- input wr_data_rise,
- input wr_data_fall,
- output rd_data_rise,
- output rd_data_fall,
- inout ddr_dq
- );
-
- wire dq_iddr_clk;
- wire dq_idelay;
- wire dq_in;
- wire dq_oe_n_r;
- wire dq_out;
- wire stg2a_out_fall;
- wire stg2a_out_rise;
- (* XIL_PAR_DELAY = "0 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
- wire stg2b_out_fall;
- (* XIL_PAR_DELAY = "0 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
- wire stg2b_out_rise;
- wire stg3a_out_fall;
- wire stg3a_out_rise;
- wire stg3b_out_fall;
- wire stg3b_out_rise;
-
- //***************************************************************************
- // Directed routing constraints for route between IDDR and stage 2 capture
- // in fabric.
- // Only 2 out of the 12 wire declarations will be used for any given
- // instantiation of this module.
- // Varies according:
- // (1) I/O column (left, center, right) used
- // (2) Which I/O in I/O pair (master, slave) used
- // Nomenclature: _Xy, X = column (0 = left, 1 = center, 2 = right),
- // y = master or slave
- //***************************************************************************
-
- // MODIFIED, RC, 06/13/08: Remove all references to DIRT, master/slave
-
- (* XIL_PAR_DELAY = "515 ps", XIL_PAR_SKEW = "55 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
- wire stg1_out_rise_sg3;
- (* XIL_PAR_DELAY = "515 ps", XIL_PAR_SKEW = "55 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
- wire stg1_out_fall_sg3;
- (* XIL_PAR_DELAY = "575 ps", XIL_PAR_SKEW = "65 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
- wire stg1_out_rise_sg2;
- (* XIL_PAR_DELAY = "575 ps", XIL_PAR_SKEW = "65 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
- wire stg1_out_fall_sg2;
- (* XIL_PAR_DELAY = "650 ps", XIL_PAR_SKEW = "70 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
- wire stg1_out_rise_sg1;
- (* XIL_PAR_DELAY = "650 ps", XIL_PAR_SKEW = "70 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
- wire stg1_out_fall_sg1;
-
- //***************************************************************************
- // Bidirectional I/O
- //***************************************************************************
-
- IOBUF u_iobuf_dq
- (
- .I (dq_out),
- .T (dq_oe_n_r),
- .IO (ddr_dq),
- .O (dq_in)
- );
-
- //***************************************************************************
- // Write (output) path
- //***************************************************************************
-
- // on a write, rising edge of DQS corresponds to rising edge of CLK180
- // (aka falling edge of CLK0 -> rising edge DQS). We also know:
- // 1. data must be driven 1/4 clk cycle before corresponding DQS edge
- // 2. first rising DQS edge driven on falling edge of CLK0
- // 3. rising data must be driven 1/4 cycle before falling edge of CLK0
- // 4. therefore, rising data driven on rising edge of CLK
- ODDR #
- (
- .SRTYPE("SYNC"),
- .DDR_CLK_EDGE("SAME_EDGE")
- )
- u_oddr_dq
- (
- .Q (dq_out),
- .C (clk90),
- .CE (1'b1),
- .D1 (wr_data_rise),
- .D2 (wr_data_fall),
- .R (1'b0),
- .S (1'b0)
- );
-
- // make sure output is tri-state during reset (DQ_OE_N_R = 1)
- ODDR #
- (
- .SRTYPE("ASYNC"),
- .DDR_CLK_EDGE("SAME_EDGE")
- )
- u_tri_state_dq
- (
- .Q (dq_oe_n_r),
- .C (clk90),
- .CE (1'b1),
- .D1 (dq_oe_n[0]),
- .D2 (dq_oe_n[1]),
- .R (1'b0),
- .S (rst90)
- );
-
- //***************************************************************************
- // Read data capture scheme description:
- // Data capture consists of 3 ranks of flops, and a MUX
- // 1. Rank 1 ("Stage 1"): IDDR captures delayed DDR DQ from memory using
- // delayed DQS.
- // - Data is split into 2 SDR streams, one each for rise and fall data.
- // - BUFIO (DQS) input inverted to IDDR. IDDR configured in SAME_EDGE
- // mode. This means that: (1) Q1 = fall data, Q2 = rise data,
- // (2) Both rise and fall data are output on falling edge of DQS -
- // rather than rise output being output on one edge of DQS, and fall
- // data on the other edge if the IDDR were configured in OPPOSITE_EDGE
- // mode. This simplifies Stage 2 capture (only one core clock edge
- // used, removing effects of duty-cycle-distortion), and saves one
- // fabric flop in Rank 3.
- // 2. Rank 2 ("Stage 2"): Fabric flops are used to capture output of first
- // rank into FPGA clock (CLK) domain. Each rising/falling SDR stream
- // from IDDR is feed into two flops, one clocked off rising and one off
- // falling edge of CLK. One of these flops is chosen, with the choice
- // being the one that reduces # of DQ/DQS taps necessary to align Stage
- // 1 and Stage 2. Same edge is used to capture both rise and fall SDR
- // streams.
- // 3. Rank 3 ("Stage 3"): Removes half-cycle paths in CLK domain from
- // output of Rank 2. This stage, like Stage 2, is clocked by CLK. Note
- // that Stage 3 can be expanded to also support SERDES functionality
- // 4. Output MUX: Selects whether Stage 1 output is aligned to rising or
- // falling edge of CLK (i.e. specifically this selects whether IDDR
- // rise/fall output is transfered to rising or falling edge of CLK).
- // Implementation:
- // 1. Rank 1 is implemented using an IDDR primitive
- // 2. Rank 2 is implemented using:
- // - An RPM to fix the location of the capture flops near the DQ I/O.
- // The exact RPM used depends on which I/O column (left, center,
- // right) the DQ I/O is placed at - this affects the optimal location
- // of the slice flops (or does it - can we always choose the two
- // columns to slices to the immediate right of the I/O to use, no
- // matter what the column?). The origin of the RPM must be set in the
- // UCF file using the RLOC_ORIGIN constraint (where the original is
- // based on the DQ I/O location).
- // - Directed Routing Constraints ("DIRT strings") to fix the routing
- // to the rank 2 fabric flops. This is done to minimize: (1) total
- // route delay (and therefore minimize voltage/temperature-related
- // variations), and (2) minimize skew both within each rising and
- // falling data net, as well as between the rising and falling nets.
- // The exact DIRT string used depends on: (1) which I/O column the
- // DQ I/O is placed, and (2) whether the DQ I/O is placed on the
- // "Master" or "Slave" I/O of a diff pair (DQ is not differential, but
- // the routing will be affected by which of each I/O pair is used)
- // 3. Rank 3 is implemented using fabric flops. No LOC or DIRT contraints
- // are used, tools are expected to place these and meet PERIOD timing
- // without constraints (constraints may be necessary for "full" designs,
- // in this case, user may need to add LOC constraints - if this is the
- // case, there are no constraints - other than meeting PERIOD timing -
- // for rank 3 flops.
- //***************************************************************************
-
- //***************************************************************************
- // MIG 2.2: Define AREA_GROUP = "DDR_CAPTURE_FFS" contain all RPM flops in
- // design. In UCF file, add constraint:
- // AREA_GROUP "DDR_CAPTURE_FFS" GROUP = CLOSED;
- // This is done to prevent MAP from packing unrelated logic into
- // the slices used by the RPMs. Doing so may cause the DIRT strings
- // that define the IDDR -> fabric flop routing to later become
- // unroutable during PAR because the unrelated logic placed by MAP
- // may use routing resources required by the DIRT strings. MAP
- // does not currently take into account DIRT strings when placing
- // logic
- //***************************************************************************
-
- // IDELAY to delay incoming data for synchronization purposes
- (* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
- (
- .DELAY_SRC ("I"),
- .IDELAY_TYPE ("VARIABLE"),
- .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
- .IDELAY_VALUE (0),
- .ODELAY_VALUE (0)
- )
- u_idelay_dq
- (
- .DATAOUT (dq_idelay),
- .C (clkdiv0),
- .CE (dlyce),
- .DATAIN (),
- .IDATAIN (dq_in),
- .INC (dlyinc),
- .ODATAIN (),
- .RST (dlyrst),
- .T ()
- );
-
- //***************************************************************************
- // Rank 1 capture: Use IDDR to generate two SDR outputs
- //***************************************************************************
-
- // invert clock to IDDR in order to use SAME_EDGE mode (otherwise, we "run
- // out of clocks" because DQS is not continuous
- assign dq_iddr_clk = ~dqs;
-
- //***************************************************************************
- // Rank 2 capture: Use fabric flops to capture Rank 1 output. Use RPM and
- // DIRT strings here.
- // BEL ("Basic Element of Logic") and relative location constraints for
- // second stage capture. C
- // Varies according:
- // (1) I/O column (left, center, right) used
- // (2) Which I/O in I/O pair (master, slave) used
- //***************************************************************************
-
- // MODIFIED, RC, 06/13/08: Remove all references to DIRT, master/slave
- // Take out generate statements - collapses to a single case
-
- generate
- if (FPGA_SPEED_GRADE == 3) begin: gen_stg2_sg3
- IDDR #
- (
- .DDR_CLK_EDGE ("SAME_EDGE")
- )
- u_iddr_dq
- (
- .Q1 (stg1_out_fall_sg3),
- .Q2 (stg1_out_rise_sg3),
- .C (dq_iddr_clk),
- .CE (ce),
- .D (dq_idelay),
- .R (1'b0),
- .S (1'b0)
- );
-
- //*********************************************************
- // Slice #1 (posedge CLK): Used for:
- // 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
- // 2. stg2 falling edge -> stg3 rising edge transfer
- //*********************************************************
-
- // Stage 2 capture
- FDRSE u_ff_stg2a_fall
- (
- .Q (stg2a_out_fall),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_fall_sg3),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- FDRSE u_ff_stg2a_rise
- (
- .Q (stg2a_out_rise),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_rise_sg3),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- // Stage 3 falling -> rising edge translation
- FDRSE u_ff_stg3b_fall
- (
- .Q (stg3b_out_fall),
- .C (clk0),
- .CE (1'b1),
- .D (stg2b_out_fall),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- FDRSE u_ff_stg3b_rise
- (
- .Q (stg3b_out_rise),
- .C (clk0),
- .CE (1'b1),
- .D (stg2b_out_rise),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
-
- //*********************************************************
- // Slice #2 (posedge CLK): Used for:
- // 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
- //*********************************************************
-
- FDRSE_1 u_ff_stg2b_fall
- (
- .Q (stg2b_out_fall),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_fall_sg3),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
-
- FDRSE_1 u_ff_stg2b_rise
- (
- .Q (stg2b_out_rise),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_rise_sg3),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- end else if (FPGA_SPEED_GRADE == 2) begin: gen_stg2_sg2
- IDDR #
- (
- .DDR_CLK_EDGE ("SAME_EDGE")
- )
- u_iddr_dq
- (
- .Q1 (stg1_out_fall_sg2),
- .Q2 (stg1_out_rise_sg2),
- .C (dq_iddr_clk),
- .CE (ce),
- .D (dq_idelay),
- .R (1'b0),
- .S (1'b0)
- );
-
- //*********************************************************
- // Slice #1 (posedge CLK): Used for:
- // 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
- // 2. stg2 falling edge -> stg3 rising edge transfer
- //*********************************************************
-
- // Stage 2 capture
- FDRSE u_ff_stg2a_fall
- (
- .Q (stg2a_out_fall),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_fall_sg2),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- FDRSE u_ff_stg2a_rise
- (
- .Q (stg2a_out_rise),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_rise_sg2),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- // Stage 3 falling -> rising edge translation
- FDRSE u_ff_stg3b_fall
- (
- .Q (stg3b_out_fall),
- .C (clk0),
- .CE (1'b1),
- .D (stg2b_out_fall),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- FDRSE u_ff_stg3b_rise
- (
- .Q (stg3b_out_rise),
- .C (clk0),
- .CE (1'b1),
- .D (stg2b_out_rise),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
-
- //*********************************************************
- // Slice #2 (posedge CLK): Used for:
- // 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
- //*********************************************************
-
- FDRSE_1 u_ff_stg2b_fall
- (
- .Q (stg2b_out_fall),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_fall_sg2),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
-
- FDRSE_1 u_ff_stg2b_rise
- (
- .Q (stg2b_out_rise),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_rise_sg2),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- end else if (FPGA_SPEED_GRADE == 1) begin: gen_stg2_sg1
- IDDR #
- (
- .DDR_CLK_EDGE ("SAME_EDGE")
- )
- u_iddr_dq
- (
- .Q1 (stg1_out_fall_sg1),
- .Q2 (stg1_out_rise_sg1),
- .C (dq_iddr_clk),
- .CE (ce),
- .D (dq_idelay),
- .R (1'b0),
- .S (1'b0)
- );
-
- //*********************************************************
- // Slice #1 (posedge CLK): Used for:
- // 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
- // 2. stg2 falling edge -> stg3 rising edge transfer
- //*********************************************************
-
- // Stage 2 capture
- FDRSE u_ff_stg2a_fall
- (
- .Q (stg2a_out_fall),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_fall_sg1),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- FDRSE u_ff_stg2a_rise
- (
- .Q (stg2a_out_rise),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_rise_sg1),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- // Stage 3 falling -> rising edge translation
- FDRSE u_ff_stg3b_fall
- (
- .Q (stg3b_out_fall),
- .C (clk0),
- .CE (1'b1),
- .D (stg2b_out_fall),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- FDRSE u_ff_stg3b_rise
- (
- .Q (stg3b_out_rise),
- .C (clk0),
- .CE (1'b1),
- .D (stg2b_out_rise),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
-
- //*********************************************************
- // Slice #2 (posedge CLK): Used for:
- // 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
- //*********************************************************
-
- FDRSE_1 u_ff_stg2b_fall
- (
- .Q (stg2b_out_fall),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_fall_sg1),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
-
- FDRSE_1 u_ff_stg2b_rise
- (
- .Q (stg2b_out_rise),
- .C (clk0),
- .CE (1'b1),
- .D (stg1_out_rise_sg1),
- .R (1'b0),
- .S (1'b0)
- )/* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- end
- endgenerate
-
- //***************************************************************************
- // Second stage flops clocked by posedge CLK0 don't need another layer of
- // registering
- //***************************************************************************
-
- assign stg3a_out_rise = stg2a_out_rise;
- assign stg3a_out_fall = stg2a_out_fall;
-
- //*******************************************************************
-
- assign rd_data_rise = (rd_data_sel) ? stg3a_out_rise : stg3b_out_rise;
- assign rd_data_fall = (rd_data_sel) ? stg3a_out_fall : stg3b_out_fall;
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_mem_if_top.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_mem_if_top.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_mem_if_top.v (nonexistent)
@@ -1,380 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_mem_if_top.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR/DDR2
-//Purpose:
-// Top-level for parameterizable (DDR or DDR2) memory interface
-//Reference:
-//Revision History:
-// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
-// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
-// Rev 1.3 - Parameter CS_BITS added. PK. 10/8/08
-// Rev 1.4 - Parameter IODELAY_GRP added. PK. 11/27/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_mem_if_top #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter CKE_WIDTH = 1,
- parameter CLK_WIDTH = 1,
- parameter COL_WIDTH = 10,
- parameter CS_BITS = 0,
- parameter CS_NUM = 1,
- parameter CS_WIDTH = 1,
- parameter USE_DM_PORT = 1,
- parameter DM_WIDTH = 9,
- parameter DQ_WIDTH = 72,
- parameter DQ_BITS = 7,
- parameter DQ_PER_DQS = 8,
- parameter DQS_BITS = 4,
- parameter DQS_WIDTH = 9,
- parameter HIGH_PERFORMANCE_MODE = "TRUE",
- parameter IODELAY_GRP = "IODELAY_MIG",
- parameter ODT_WIDTH = 1,
- parameter ROW_WIDTH = 14,
- parameter APPDATA_WIDTH = 144,
- parameter ADDITIVE_LAT = 0,
- parameter BURST_LEN = 4,
- parameter BURST_TYPE = 0,
- parameter CAS_LAT = 5,
- parameter ECC_ENABLE = 0,
- parameter MULTI_BANK_EN = 1,
- parameter TWO_T_TIME_EN = 0,
- parameter ODT_TYPE = 1,
- parameter DDR_TYPE = 1,
- parameter REDUCE_DRV = 0,
- parameter REG_ENABLE = 1,
- parameter TREFI_NS = 7800,
- parameter TRAS = 40000,
- parameter TRCD = 15000,
- parameter TRFC = 105000,
- parameter TRP = 15000,
- parameter TRTP = 7500,
- parameter TWR = 15000,
- parameter TWTR = 10000,
- parameter CLK_PERIOD = 3000,
- parameter SIM_ONLY = 0,
- parameter DEBUG_EN = 0,
- parameter FPGA_SPEED_GRADE = 2
- )
- (
- input clk0,
- input clk90,
- input clkdiv0,
- input rst0,
- input rst90,
- input rstdiv0,
- input [2:0] app_af_cmd,
- input [30:0] app_af_addr,
- input app_af_wren,
- input app_wdf_wren,
- input [APPDATA_WIDTH-1:0] app_wdf_data,
- input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
- output [1:0] rd_ecc_error,
- output app_af_afull,
- output app_wdf_afull,
- output rd_data_valid,
- output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
- output phy_init_done,
- output [CLK_WIDTH-1:0] ddr_ck,
- output [CLK_WIDTH-1:0] ddr_ck_n,
- output [ROW_WIDTH-1:0] ddr_addr,
- output [BANK_WIDTH-1:0] ddr_ba,
- output ddr_ras_n,
- output ddr_cas_n,
- output ddr_we_n,
- output [CS_WIDTH-1:0] ddr_cs_n,
- output [CKE_WIDTH-1:0] ddr_cke,
- output [ODT_WIDTH-1:0] ddr_odt,
- output [DM_WIDTH-1:0] ddr_dm,
- inout [DQS_WIDTH-1:0] ddr_dqs,
- inout [DQS_WIDTH-1:0] ddr_dqs_n,
- inout [DQ_WIDTH-1:0] ddr_dq,
- // Debug signals (optional use)
- input dbg_idel_up_all,
- input dbg_idel_down_all,
- input dbg_idel_up_dq,
- input dbg_idel_down_dq,
- input dbg_idel_up_dqs,
- input dbg_idel_down_dqs,
- input dbg_idel_up_gate,
- input dbg_idel_down_gate,
- input [DQ_BITS-1:0] dbg_sel_idel_dq,
- input dbg_sel_all_idel_dq,
- input [DQS_BITS:0] dbg_sel_idel_dqs,
- input dbg_sel_all_idel_dqs,
- input [DQS_BITS:0] dbg_sel_idel_gate,
- input dbg_sel_all_idel_gate,
- output [3:0] dbg_calib_done,
- output [3:0] dbg_calib_err,
- output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
- output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
- );
-
- wire [30:0] af_addr;
- wire [2:0] af_cmd;
- wire af_empty;
- wire [ROW_WIDTH-1:0] ctrl_addr;
- wire ctrl_af_rden;
- wire [BANK_WIDTH-1:0] ctrl_ba;
- wire ctrl_cas_n;
- wire [CS_NUM-1:0] ctrl_cs_n;
- wire ctrl_ras_n;
- wire ctrl_rden;
- wire ctrl_ref_flag;
- wire ctrl_we_n;
- wire ctrl_wren;
- wire [DQS_WIDTH-1:0] phy_calib_rden;
- wire [DQS_WIDTH-1:0] phy_calib_rden_sel;
- wire [DQ_WIDTH-1:0] rd_data_fall;
- wire [DQ_WIDTH-1:0] rd_data_rise;
- wire [(2*DQ_WIDTH)-1:0] wdf_data;
- wire [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data;
- wire wdf_rden;
-
- //***************************************************************************
-
- ddr2_phy_top #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .CKE_WIDTH (CKE_WIDTH),
- .CLK_WIDTH (CLK_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .CS_BITS (CS_BITS),
- .CS_NUM (CS_NUM),
- .CS_WIDTH (CS_WIDTH),
- .USE_DM_PORT (USE_DM_PORT),
- .DM_WIDTH (DM_WIDTH),
- .DQ_WIDTH (DQ_WIDTH),
- .DQ_BITS (DQ_BITS),
- .DQ_PER_DQS (DQ_PER_DQS),
- .DQS_BITS (DQS_BITS),
- .DQS_WIDTH (DQS_WIDTH),
- .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
- .IODELAY_GRP (IODELAY_GRP),
- .ODT_WIDTH (ODT_WIDTH),
- .ROW_WIDTH (ROW_WIDTH),
- .TWO_T_TIME_EN (TWO_T_TIME_EN),
- .ADDITIVE_LAT (ADDITIVE_LAT),
- .BURST_LEN (BURST_LEN),
- .BURST_TYPE (BURST_TYPE),
- .CAS_LAT (CAS_LAT),
- .ECC_ENABLE (ECC_ENABLE),
- .ODT_TYPE (ODT_TYPE),
- .DDR_TYPE (DDR_TYPE),
- .REDUCE_DRV (REDUCE_DRV),
- .REG_ENABLE (REG_ENABLE),
- .TWR (TWR),
- .CLK_PERIOD (CLK_PERIOD),
- .SIM_ONLY (SIM_ONLY),
- .DEBUG_EN (DEBUG_EN),
- .FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
- )
- u_phy_top
- (
- .clk0 (clk0),
- .clk90 (clk90),
- .clkdiv0 (clkdiv0),
- .rst0 (rst0),
- .rst90 (rst90),
- .rstdiv0 (rstdiv0),
- .ctrl_wren (ctrl_wren),
- .ctrl_addr (ctrl_addr),
- .ctrl_ba (ctrl_ba),
- .ctrl_ras_n (ctrl_ras_n),
- .ctrl_cas_n (ctrl_cas_n),
- .ctrl_we_n (ctrl_we_n),
- .ctrl_cs_n (ctrl_cs_n),
- .ctrl_rden (ctrl_rden),
- .ctrl_ref_flag (ctrl_ref_flag),
- .wdf_data (wdf_data),
- .wdf_mask_data (wdf_mask_data),
- .wdf_rden (wdf_rden),
- .phy_init_done (phy_init_done),
- .phy_calib_rden (phy_calib_rden),
- .phy_calib_rden_sel (phy_calib_rden_sel),
- .rd_data_rise (rd_data_rise),
- .rd_data_fall (rd_data_fall),
- .ddr_ck (ddr_ck),
- .ddr_ck_n (ddr_ck_n),
- .ddr_addr (ddr_addr),
- .ddr_ba (ddr_ba),
- .ddr_ras_n (ddr_ras_n),
- .ddr_cas_n (ddr_cas_n),
- .ddr_we_n (ddr_we_n),
- .ddr_cs_n (ddr_cs_n),
- .ddr_cke (ddr_cke),
- .ddr_odt (ddr_odt),
- .ddr_dm (ddr_dm),
- .ddr_dqs (ddr_dqs),
- .ddr_dqs_n (ddr_dqs_n),
- .ddr_dq (ddr_dq),
- .dbg_idel_up_all (dbg_idel_up_all),
- .dbg_idel_down_all (dbg_idel_down_all),
- .dbg_idel_up_dq (dbg_idel_up_dq),
- .dbg_idel_down_dq (dbg_idel_down_dq),
- .dbg_idel_up_dqs (dbg_idel_up_dqs),
- .dbg_idel_down_dqs (dbg_idel_down_dqs),
- .dbg_idel_up_gate (dbg_idel_up_gate),
- .dbg_idel_down_gate (dbg_idel_down_gate),
- .dbg_sel_idel_dq (dbg_sel_idel_dq),
- .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
- .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
- .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
- .dbg_sel_idel_gate (dbg_sel_idel_gate),
- .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
- .dbg_calib_done (dbg_calib_done),
- .dbg_calib_err (dbg_calib_err),
- .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
- .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
- .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
- .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
- .dbg_calib_rden_dly (dbg_calib_rden_dly),
- .dbg_calib_gate_dly (dbg_calib_gate_dly)
- );
-
- ddr2_usr_top #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .CS_BITS (CS_BITS),
- .DQ_WIDTH (DQ_WIDTH),
- .DQ_PER_DQS (DQ_PER_DQS),
- .DQS_WIDTH (DQS_WIDTH),
- .APPDATA_WIDTH (APPDATA_WIDTH),
- .ECC_ENABLE (ECC_ENABLE),
- .ROW_WIDTH (ROW_WIDTH)
- )
- u_usr_top
- (
- .clk0 (clk0),
- .clk90 (clk90),
- .rst0 (rst0),
- .rd_data_in_rise (rd_data_rise),
- .rd_data_in_fall (rd_data_fall),
- .phy_calib_rden (phy_calib_rden),
- .phy_calib_rden_sel(phy_calib_rden_sel),
- .rd_data_valid (rd_data_valid),
- .rd_ecc_error (rd_ecc_error),
- .rd_data_fifo_out (rd_data_fifo_out),
- .app_af_cmd (app_af_cmd),
- .app_af_addr (app_af_addr),
- .app_af_wren (app_af_wren),
- .ctrl_af_rden (ctrl_af_rden),
- .af_cmd (af_cmd),
- .af_addr (af_addr),
- .af_empty (af_empty),
- .app_af_afull (app_af_afull),
- .app_wdf_wren (app_wdf_wren),
- .app_wdf_data (app_wdf_data),
- .app_wdf_mask_data (app_wdf_mask_data),
- .wdf_rden (wdf_rden),
- .app_wdf_afull (app_wdf_afull),
- .wdf_data (wdf_data),
- .wdf_mask_data (wdf_mask_data)
- );
-
-
- ddr2_ctrl #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .CS_BITS (CS_BITS),
- .CS_NUM (CS_NUM),
- .ROW_WIDTH (ROW_WIDTH),
- .ADDITIVE_LAT (ADDITIVE_LAT),
- .BURST_LEN (BURST_LEN),
- .CAS_LAT (CAS_LAT),
- .ECC_ENABLE (ECC_ENABLE),
- .REG_ENABLE (REG_ENABLE),
- .MULTI_BANK_EN (MULTI_BANK_EN),
- .TWO_T_TIME_EN (TWO_T_TIME_EN),
- .TREFI_NS (TREFI_NS),
- .TRAS (TRAS),
- .TRCD (TRCD),
- .TRFC (TRFC),
- .TRP (TRP),
- .TRTP (TRTP),
- .TWR (TWR),
- .TWTR (TWTR),
- .CLK_PERIOD (CLK_PERIOD),
- .DDR_TYPE (DDR_TYPE)
- )
- u_ctrl
- (
- .clk (clk0),
- .rst (rst0),
- .af_cmd (af_cmd),
- .af_addr (af_addr),
- .af_empty (af_empty),
- .phy_init_done (phy_init_done),
- .ctrl_ref_flag (ctrl_ref_flag),
- .ctrl_af_rden (ctrl_af_rden),
- .ctrl_wren (ctrl_wren),
- .ctrl_rden (ctrl_rden),
- .ctrl_addr (ctrl_addr),
- .ctrl_ba (ctrl_ba),
- .ctrl_ras_n (ctrl_ras_n),
- .ctrl_cas_n (ctrl_cas_n),
- .ctrl_we_n (ctrl_we_n),
- .ctrl_cs_n (ctrl_cs_n)
- );
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_infrastructure.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_infrastructure.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_infrastructure.v (nonexistent)
@@ -1,150 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_infrastructure.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// Clock distribution and reset synchronization
-//Reference:
-//Revision History:
-// Rev 1.1 - Port name changed from dcm_lock to locked. PK. 10/14/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_infrastructure #
- (
- parameter RST_ACT_LOW = 1
- )
- (
- input clk0,
- input clk90,
- input clk200,
- input clkdiv0,
- input locked,
- input sys_rst_n,
- input idelay_ctrl_rdy,
- output rst0,
- output rst90,
- output rst200,
- output rstdiv0
- );
-
- // # of clock cycles to delay deassertion of reset. Needs to be a fairly
- // high number not so much for metastability protection, but to give time
- // for reset (i.e. stable clock cycles) to propagate through all state
- // machines and to all control signals (i.e. not all control signals have
- // resets, instead they rely on base state logic being reset, and the effect
- // of that reset propagating through the logic). Need this because we may not
- // be getting stable clock cycles while reset asserted (i.e. since reset
- // depends on DCM lock status)
- localparam RST_SYNC_NUM = 25;
-
- reg [RST_SYNC_NUM-1:0] rst0_sync_r /* synthesis syn_maxfan = 10 */;
- reg [RST_SYNC_NUM-1:0] rst200_sync_r /* synthesis syn_maxfan = 10 */;
- reg [RST_SYNC_NUM-1:0] rst90_sync_r /* synthesis syn_maxfan = 10 */;
- reg [(RST_SYNC_NUM/2)-1:0] rstdiv0_sync_r /* synthesis syn_maxfan = 10 */;
- wire rst_tmp;
- wire sys_clk_ibufg;
- wire sys_rst;
-
- assign sys_rst = RST_ACT_LOW ? ~sys_rst_n: sys_rst_n;
-
- //***************************************************************************
- // Reset synchronization
- // NOTES:
- // 1. shut down the whole operation if the DCM hasn't yet locked (and by
- // inference, this means that external SYS_RST_IN has been asserted -
- // DCM deasserts LOCKED as soon as SYS_RST_IN asserted)
- // 2. In the case of all resets except rst200, also assert reset if the
- // IDELAY master controller is not yet ready
- // 3. asynchronously assert reset. This was we can assert reset even if
- // there is no clock (needed for things like 3-stating output buffers).
- // reset deassertion is synchronous.
- //***************************************************************************
-
- assign rst_tmp = sys_rst | ~locked | ~idelay_ctrl_rdy;
-
- // synthesis attribute max_fanout of rst0_sync_r is 10
- always @(posedge clk0 or posedge rst_tmp)
- if (rst_tmp)
- rst0_sync_r <= {RST_SYNC_NUM{1'b1}};
- else
- // logical left shift by one (pads with 0)
- rst0_sync_r <= rst0_sync_r << 1;
-
- // synthesis attribute max_fanout of rstdiv0_sync_r is 10
- always @(posedge clkdiv0 or posedge rst_tmp)
- if (rst_tmp)
- rstdiv0_sync_r <= {(RST_SYNC_NUM/2){1'b1}};
- else
- // logical left shift by one (pads with 0)
- rstdiv0_sync_r <= rstdiv0_sync_r << 1;
-
- // synthesis attribute max_fanout of rst90_sync_r is 10
- always @(posedge clk90 or posedge rst_tmp)
- if (rst_tmp)
- rst90_sync_r <= {RST_SYNC_NUM{1'b1}};
- else
- rst90_sync_r <= rst90_sync_r << 1;
-
- // make sure CLK200 doesn't depend on IDELAY_CTRL_RDY, else chicken n' egg
- // synthesis attribute max_fanout of rst200_sync_r is 10
- always @(posedge clk200 or negedge locked)
- if (!locked)
- rst200_sync_r <= {RST_SYNC_NUM{1'b1}};
- else
- rst200_sync_r <= rst200_sync_r << 1;
-
- assign rst0 = rst0_sync_r[RST_SYNC_NUM-1];
- assign rst90 = rst90_sync_r[RST_SYNC_NUM-1];
- assign rst200 = rst200_sync_r[RST_SYNC_NUM-1];
- assign rstdiv0 = rstdiv0_sync_r[(RST_SYNC_NUM/2)-1];
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_wr.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_wr.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_wr.v (nonexistent)
@@ -1,334 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_usr_wr.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Mon Aug 28 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR/DDR2
-//Purpose:
-// This module instantiates the modules containing internal FIFOs
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_usr_wr #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter COL_WIDTH = 10,
- parameter CS_BITS = 0,
- parameter DQ_WIDTH = 72,
- parameter APPDATA_WIDTH = 144,
- parameter ECC_ENABLE = 0,
- parameter ROW_WIDTH = 14
- )
- (
- input clk0,
- input clk90,
- input rst0,
- // Write data FIFO interface
- input app_wdf_wren,
- input [APPDATA_WIDTH-1:0] app_wdf_data,
- input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
- input wdf_rden,
- output app_wdf_afull,
- output [(2*DQ_WIDTH)-1:0] wdf_data,
- output [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data
- );
-
- // determine number of FIFO72's to use based on data width
- // round up to next integer value when determining WDF_FIFO_NUM
- localparam WDF_FIFO_NUM = (ECC_ENABLE) ? (APPDATA_WIDTH+63)/64 :
- ((2*DQ_WIDTH)+63)/64;
- // MASK_WIDTH = number of bytes in data bus
- localparam MASK_WIDTH = DQ_WIDTH/8;
-
- wire [WDF_FIFO_NUM-1:0] i_wdf_afull;
- wire [DQ_WIDTH-1:0] i_wdf_data_fall_in;
- wire [DQ_WIDTH-1:0] i_wdf_data_fall_out;
- wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_in;
- wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_out;
- wire [DQ_WIDTH-1:0] i_wdf_data_rise_in;
- wire [DQ_WIDTH-1:0] i_wdf_data_rise_out;
- wire [MASK_WIDTH-1:0] i_wdf_mask_data_fall_in;
- wire [MASK_WIDTH-1:0] i_wdf_mask_data_fall_out;
- wire [(8*WDF_FIFO_NUM)-1:0] i_wdf_mask_data_in;
- wire [(8*WDF_FIFO_NUM)-1:0] i_wdf_mask_data_out;
- wire [MASK_WIDTH-1:0] i_wdf_mask_data_rise_in;
- wire [MASK_WIDTH-1:0] i_wdf_mask_data_rise_out;
- reg rst_r;
-
- // ECC signals
- wire [(2*DQ_WIDTH)-1:0] i_wdf_data_out_ecc;
- wire [((2*DQ_WIDTH)/8)-1:0] i_wdf_mask_data_out_ecc;
- wire [63:0] i_wdf_mask_data_out_ecc_wire;
- wire [((2*DQ_WIDTH)/8)-1:0] mask_data_in_ecc;
- wire [63:0] mask_data_in_ecc_wire;
-
- //***************************************************************************
-
- assign app_wdf_afull = i_wdf_afull[0];
-
- always @(posedge clk0 )
- rst_r <= rst0;
-
- genvar wdf_di_i;
- genvar wdf_do_i;
- genvar mask_i;
- genvar wdf_i;
- generate
- if(ECC_ENABLE) begin // ECC code
-
- assign wdf_data = i_wdf_data_out_ecc;
-
- // the byte 9 dm is always held to 0
- assign wdf_mask_data = i_wdf_mask_data_out_ecc;
-
-
-
- // generate for write data fifo .
- for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
-
- FIFO36_72 #
- (
- .ALMOST_EMPTY_OFFSET (9'h007),
- .ALMOST_FULL_OFFSET (9'h00F),
- .DO_REG (1), // extra CC output delay
- .EN_ECC_WRITE ("TRUE"),
- .EN_ECC_READ ("FALSE"),
- .EN_SYN ("FALSE"),
- .FIRST_WORD_FALL_THROUGH ("FALSE")
- )
- u_wdf_ecc
- (
- .ALMOSTEMPTY (),
- .ALMOSTFULL (i_wdf_afull[wdf_i]),
- .DBITERR (),
- .DO (i_wdf_data_out_ecc[((64*(wdf_i+1))+(wdf_i *8))-1:
- (64*wdf_i)+(wdf_i *8)]),
- .DOP (i_wdf_data_out_ecc[(72*(wdf_i+1))-1:
- (64*(wdf_i+1))+ (8*wdf_i) ]),
- .ECCPARITY (),
- .EMPTY (),
- .FULL (),
- .RDCOUNT (),
- .RDERR (),
- .SBITERR (),
- .WRCOUNT (),
- .WRERR (),
- .DI (app_wdf_data[(64*(wdf_i+1))-1:
- (64*wdf_i)]),
- .DIP (),
- .RDCLK (clk90),
- .RDEN (wdf_rden),
- .RST (rst_r), // or can use rst0
- .WRCLK (clk0),
- .WREN (app_wdf_wren)
- );
- end
-
- // remapping the mask data. The mask data from user i/f does not have
- // the mask for the ECC byte. Assigning 0 to the ECC mask byte.
- for (mask_i = 0; mask_i < (DQ_WIDTH)/36;
- mask_i = mask_i +1) begin: gen_mask
- assign mask_data_in_ecc[((8*(mask_i+1))+ mask_i)-1:((8*mask_i)+mask_i)]
- = app_wdf_mask_data[(8*(mask_i+1))-1:8*(mask_i)] ;
- assign mask_data_in_ecc[((8*(mask_i+1))+mask_i)] = 1'd0;
- end
-
- // assign ecc bits to temp variables to avoid
- // sim warnings. Not all the 64 bits of the fifo
- // are used in ECC mode.
- assign mask_data_in_ecc_wire[((2*DQ_WIDTH)/8)-1:0] = mask_data_in_ecc;
- assign mask_data_in_ecc_wire[63:((2*DQ_WIDTH)/8)] =
- {(64-((2*DQ_WIDTH)/8)){1'b0}};
- assign i_wdf_mask_data_out_ecc =
- i_wdf_mask_data_out_ecc_wire[((2*DQ_WIDTH)/8)-1:0];
-
-
- FIFO36_72 #
- (
- .ALMOST_EMPTY_OFFSET (9'h007),
- .ALMOST_FULL_OFFSET (9'h00F),
- .DO_REG (1), // extra CC output delay
- .EN_ECC_WRITE ("TRUE"),
- .EN_ECC_READ ("FALSE"),
- .EN_SYN ("FALSE"),
- .FIRST_WORD_FALL_THROUGH ("FALSE")
- )
- u_wdf_ecc_mask
- (
- .ALMOSTEMPTY (),
- .ALMOSTFULL (),
- .DBITERR (),
- .DO (i_wdf_mask_data_out_ecc_wire),
- .DOP (),
- .ECCPARITY (),
- .EMPTY (),
- .FULL (),
- .RDCOUNT (),
- .RDERR (),
- .SBITERR (),
- .WRCOUNT (),
- .WRERR (),
- .DI (mask_data_in_ecc_wire),
- .DIP (),
- .RDCLK (clk90),
- .RDEN (wdf_rden),
- .RST (rst_r), // or can use rst0
- .WRCLK (clk0),
- .WREN (app_wdf_wren)
- );
- end else begin
-
- //***********************************************************************
-
- // Define intermediate buses:
- assign i_wdf_data_rise_in
- = app_wdf_data[DQ_WIDTH-1:0];
- assign i_wdf_data_fall_in
- = app_wdf_data[(2*DQ_WIDTH)-1:DQ_WIDTH];
- assign i_wdf_mask_data_rise_in
- = app_wdf_mask_data[MASK_WIDTH-1:0];
- assign i_wdf_mask_data_fall_in
- = app_wdf_mask_data[(2*MASK_WIDTH)-1:MASK_WIDTH];
-
- //***********************************************************************
- // Write data FIFO Input:
- // Arrange DQ's so that the rise data and fall data are interleaved.
- // the data arrives at the input of the wdf fifo as {fall,rise}.
- // It is remapped as:
- // {...fall[15:8],rise[15:8],fall[7:0],rise[7:0]}
- // This is done to avoid having separate fifo's for rise and fall data
- // and to keep rise/fall data for the same DQ's on same FIFO
- // Data masks are interleaved in a similar manner
- // NOTE: Initialization data from PHY_INIT module does not need to be
- // interleaved - it's already in the correct format - and the same
- // initialization pattern from PHY_INIT is sent to all write FIFOs
- //***********************************************************************
-
- for (wdf_di_i = 0; wdf_di_i < MASK_WIDTH;
- wdf_di_i = wdf_di_i + 1) begin: gen_wdf_data_in
- assign i_wdf_data_in[(16*wdf_di_i)+15:(16*wdf_di_i)]
- = {i_wdf_data_fall_in[(8*wdf_di_i)+7:(8*wdf_di_i)],
- i_wdf_data_rise_in[(8*wdf_di_i)+7:(8*wdf_di_i)]};
- assign i_wdf_mask_data_in[(2*wdf_di_i)+1:(2*wdf_di_i)]
- = {i_wdf_mask_data_fall_in[wdf_di_i],
- i_wdf_mask_data_rise_in[wdf_di_i]};
- end
-
- //***********************************************************************
- // Write data FIFO Output:
- // FIFO DQ and mask outputs must be untangled and put in the standard
- // format of {fall,rise}. Same goes for mask output
- //***********************************************************************
-
- for (wdf_do_i = 0; wdf_do_i < MASK_WIDTH;
- wdf_do_i = wdf_do_i + 1) begin: gen_wdf_data_out
- assign i_wdf_data_rise_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
- = i_wdf_data_out[(16*wdf_do_i)+7:(16*wdf_do_i)];
- assign i_wdf_data_fall_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
- = i_wdf_data_out[(16*wdf_do_i)+15:(16*wdf_do_i)+8];
- assign i_wdf_mask_data_rise_out[wdf_do_i]
- = i_wdf_mask_data_out[2*wdf_do_i];
- assign i_wdf_mask_data_fall_out[wdf_do_i]
- = i_wdf_mask_data_out[(2*wdf_do_i)+1];
- end
-
- assign wdf_data = {i_wdf_data_fall_out,
- i_wdf_data_rise_out};
-
- assign wdf_mask_data = {i_wdf_mask_data_fall_out,
- i_wdf_mask_data_rise_out};
-
- //***********************************************************************
-
- for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
-
- FIFO36_72 #
- (
- .ALMOST_EMPTY_OFFSET (9'h007),
- .ALMOST_FULL_OFFSET (9'h00F),
- .DO_REG (1), // extra CC output delay
- .EN_ECC_WRITE ("FALSE"),
- .EN_ECC_READ ("FALSE"),
- .EN_SYN ("FALSE"),
- .FIRST_WORD_FALL_THROUGH ("FALSE")
- )
- u_wdf
- (
- .ALMOSTEMPTY (),
- .ALMOSTFULL (i_wdf_afull[wdf_i]),
- .DBITERR (),
- .DO (i_wdf_data_out[(64*(wdf_i+1))-1:64*wdf_i]),
- .DOP (i_wdf_mask_data_out[(8*(wdf_i+1))-1:8*wdf_i]),
- .ECCPARITY (),
- .EMPTY (),
- .FULL (),
- .RDCOUNT (),
- .RDERR (),
- .SBITERR (),
- .WRCOUNT (),
- .WRERR (),
- .DI (i_wdf_data_in[(64*(wdf_i+1))-1:64*wdf_i]),
- .DIP (i_wdf_mask_data_in[(8*(wdf_i+1))-1:8*wdf_i]),
- .RDCLK (clk90),
- .RDEN (wdf_rden),
- .RST (rst_r), // or can use rst0
- .WRCLK (clk0),
- .WREN (app_wdf_wren)
- );
- end
- end
- endgenerate
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_top.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_top.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_top.v (nonexistent)
@@ -1,395 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_phy_top.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// Top-level for memory physical layer (PHY) interface
-//Reference:
-//Revision History:
-// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
-// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
-// Rev 1.3 - Parameter CS_BITS added. PK. 10/8/08
-// Rev 1.4 - Parameter IODELAY_GRP added. PK. 11/27/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-(* X_CORE_INFO = "mig_v3_61_ddr2_sdram_v5, Coregen 12.4" , CORE_GENERATION_INFO = "ddr2_sdram_v5,mig_v3_61,{component_name=ddr2_phy_top, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=3, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, CLK_PERIOD=8000, RST_ACT_LOW=1, INTERFACE_TYPE=DDR2_SDRAM, LANGUAGE=Verilog, SYNTHESIS_TOOL=ISE, NO_OF_CONTROLLERS=1}" *)
-module ddr2_phy_top #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter CLK_WIDTH = 1,
- parameter CKE_WIDTH = 1,
- parameter COL_WIDTH = 10,
- parameter CS_BITS = 0,
- parameter CS_NUM = 1,
- parameter CS_WIDTH = 1,
- parameter USE_DM_PORT = 1,
- parameter DM_WIDTH = 9,
- parameter DQ_WIDTH = 72,
- parameter DQ_BITS = 7,
- parameter DQ_PER_DQS = 8,
- parameter DQS_WIDTH = 9,
- parameter DQS_BITS = 4,
- parameter HIGH_PERFORMANCE_MODE = "TRUE",
- parameter IODELAY_GRP = "IODELAY_MIG",
- parameter ODT_WIDTH = 1,
- parameter ROW_WIDTH = 14,
- parameter ADDITIVE_LAT = 0,
- parameter TWO_T_TIME_EN = 0,
- parameter BURST_LEN = 4,
- parameter BURST_TYPE = 0,
- parameter CAS_LAT = 5,
- parameter TWR = 15000,
- parameter ECC_ENABLE = 0,
- parameter ODT_TYPE = 1,
- parameter DDR_TYPE = 1,
- parameter REDUCE_DRV = 0,
- parameter REG_ENABLE = 1,
- parameter CLK_PERIOD = 3000,
- parameter SIM_ONLY = 0,
- parameter DEBUG_EN = 0,
- parameter FPGA_SPEED_GRADE = 2
- )
- (
- input clk0,
- input clk90,
- input clkdiv0,
- input rst0,
- input rst90,
- input rstdiv0,
- input ctrl_wren,
- input [ROW_WIDTH-1:0] ctrl_addr,
- input [BANK_WIDTH-1:0] ctrl_ba,
- input ctrl_ras_n,
- input ctrl_cas_n,
- input ctrl_we_n,
- input [CS_NUM-1:0] ctrl_cs_n,
- input ctrl_rden,
- input ctrl_ref_flag,
- input [(2*DQ_WIDTH)-1:0] wdf_data,
- input [(2*DQ_WIDTH/8)-1:0] wdf_mask_data,
- output wdf_rden,
- output phy_init_done,
- output [DQS_WIDTH-1:0] phy_calib_rden,
- output [DQS_WIDTH-1:0] phy_calib_rden_sel,
- output [DQ_WIDTH-1:0] rd_data_rise,
- output [DQ_WIDTH-1:0] rd_data_fall,
- output [CLK_WIDTH-1:0] ddr_ck,
- output [CLK_WIDTH-1:0] ddr_ck_n,
- output [ROW_WIDTH-1:0] ddr_addr,
- output [BANK_WIDTH-1:0] ddr_ba,
- output ddr_ras_n,
- output ddr_cas_n,
- output ddr_we_n,
- output [CS_WIDTH-1:0] ddr_cs_n,
- output [CKE_WIDTH-1:0] ddr_cke,
- output [ODT_WIDTH-1:0] ddr_odt,
- output [DM_WIDTH-1:0] ddr_dm,
- inout [DQS_WIDTH-1:0] ddr_dqs,
- inout [DQS_WIDTH-1:0] ddr_dqs_n,
- inout [DQ_WIDTH-1:0] ddr_dq,
- // Debug signals (optional use)
- input dbg_idel_up_all,
- input dbg_idel_down_all,
- input dbg_idel_up_dq,
- input dbg_idel_down_dq,
- input dbg_idel_up_dqs,
- input dbg_idel_down_dqs,
- input dbg_idel_up_gate,
- input dbg_idel_down_gate,
- input [DQ_BITS-1:0] dbg_sel_idel_dq,
- input dbg_sel_all_idel_dq,
- input [DQS_BITS:0] dbg_sel_idel_dqs,
- input dbg_sel_all_idel_dqs,
- input [DQS_BITS:0] dbg_sel_idel_gate,
- input dbg_sel_all_idel_gate,
- output [3:0] dbg_calib_done,
- output [3:0] dbg_calib_err,
- output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
- output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
- );
-
- wire [3:0] calib_done;
- wire calib_ref_done;
- wire calib_ref_req;
- wire [3:0] calib_start;
- wire dm_ce;
- wire [1:0] dq_oe_n;
- wire dqs_oe_n;
- wire dqs_rst_n;
- wire [(DQ_WIDTH/8)-1:0] mask_data_fall;
- wire [(DQ_WIDTH/8)-1:0] mask_data_rise;
- wire [CS_NUM-1:0] odt;
- wire [ROW_WIDTH-1:0] phy_init_addr;
- wire [BANK_WIDTH-1:0] phy_init_ba;
- wire phy_init_cas_n;
- wire [CKE_WIDTH-1:0] phy_init_cke;
- wire [CS_NUM-1:0] phy_init_cs_n;
- wire phy_init_data_sel;
- wire phy_init_ras_n;
- wire phy_init_rden;
- wire phy_init_we_n;
- wire phy_init_wren;
- wire [DQ_WIDTH-1:0] wr_data_fall;
- wire [DQ_WIDTH-1:0] wr_data_rise;
-
- //***************************************************************************
-
- ddr2_phy_write #
- (
- .DQ_WIDTH (DQ_WIDTH),
- .CS_NUM (CS_NUM),
- .ADDITIVE_LAT (ADDITIVE_LAT),
- .CAS_LAT (CAS_LAT),
- .ECC_ENABLE (ECC_ENABLE),
- .ODT_TYPE (ODT_TYPE),
- .REG_ENABLE (REG_ENABLE),
- .DDR_TYPE (DDR_TYPE)
- )
- u_phy_write
- (
- .clk0 (clk0),
- .clk90 (clk90),
- .rst90 (rst90),
- .wdf_data (wdf_data),
- .wdf_mask_data (wdf_mask_data),
- .ctrl_wren (ctrl_wren),
- .phy_init_wren (phy_init_wren),
- .phy_init_data_sel (phy_init_data_sel),
- .dm_ce (dm_ce),
- .dq_oe_n (dq_oe_n),
- .dqs_oe_n (dqs_oe_n),
- .dqs_rst_n (dqs_rst_n),
- .wdf_rden (wdf_rden),
- .odt (odt),
- .wr_data_rise (wr_data_rise),
- .wr_data_fall (wr_data_fall),
- .mask_data_rise (mask_data_rise),
- .mask_data_fall (mask_data_fall)
- );
-
- ddr2_phy_io #
- (
- .CLK_WIDTH (CLK_WIDTH),
- .USE_DM_PORT (USE_DM_PORT),
- .DM_WIDTH (DM_WIDTH),
- .DQ_WIDTH (DQ_WIDTH),
- .DQ_BITS (DQ_BITS),
- .DQ_PER_DQS (DQ_PER_DQS),
- .DQS_BITS (DQS_BITS),
- .DQS_WIDTH (DQS_WIDTH),
- .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
- .IODELAY_GRP (IODELAY_GRP),
- .ODT_WIDTH (ODT_WIDTH),
- .ADDITIVE_LAT (ADDITIVE_LAT),
- .CAS_LAT (CAS_LAT),
- .REG_ENABLE (REG_ENABLE),
- .CLK_PERIOD (CLK_PERIOD),
- .DDR_TYPE (DDR_TYPE),
- .SIM_ONLY (SIM_ONLY),
- .DEBUG_EN (DEBUG_EN),
- .FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
- )
- u_phy_io
- (
- .clk0 (clk0),
- .clk90 (clk90),
- .clkdiv0 (clkdiv0),
- .rst0 (rst0),
- .rst90 (rst90),
- .rstdiv0 (rstdiv0),
- .dm_ce (dm_ce),
- .dq_oe_n (dq_oe_n),
- .dqs_oe_n (dqs_oe_n),
- .dqs_rst_n (dqs_rst_n),
- .calib_start (calib_start),
- .ctrl_rden (ctrl_rden),
- .phy_init_rden (phy_init_rden),
- .calib_ref_done (calib_ref_done),
- .calib_done (calib_done),
- .calib_ref_req (calib_ref_req),
- .calib_rden (phy_calib_rden),
- .calib_rden_sel (phy_calib_rden_sel),
- .wr_data_rise (wr_data_rise),
- .wr_data_fall (wr_data_fall),
- .mask_data_rise (mask_data_rise),
- .mask_data_fall (mask_data_fall),
- .rd_data_rise (rd_data_rise),
- .rd_data_fall (rd_data_fall),
- .ddr_ck (ddr_ck),
- .ddr_ck_n (ddr_ck_n),
- .ddr_dm (ddr_dm),
- .ddr_dqs (ddr_dqs),
- .ddr_dqs_n (ddr_dqs_n),
- .ddr_dq (ddr_dq),
- .dbg_idel_up_all (dbg_idel_up_all),
- .dbg_idel_down_all (dbg_idel_down_all),
- .dbg_idel_up_dq (dbg_idel_up_dq),
- .dbg_idel_down_dq (dbg_idel_down_dq),
- .dbg_idel_up_dqs (dbg_idel_up_dqs),
- .dbg_idel_down_dqs (dbg_idel_down_dqs),
- .dbg_idel_up_gate (dbg_idel_up_gate),
- .dbg_idel_down_gate (dbg_idel_down_gate),
- .dbg_sel_idel_dq (dbg_sel_idel_dq),
- .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
- .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
- .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
- .dbg_sel_idel_gate (dbg_sel_idel_gate),
- .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
- .dbg_calib_done (dbg_calib_done),
- .dbg_calib_err (dbg_calib_err),
- .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
- .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
- .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
- .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
- .dbg_calib_rden_dly (dbg_calib_rden_dly),
- .dbg_calib_gate_dly (dbg_calib_gate_dly)
- );
-
- ddr2_phy_ctl_io #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .CKE_WIDTH (CKE_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .CS_NUM (CS_NUM),
- .CS_WIDTH (CS_WIDTH),
- .TWO_T_TIME_EN (TWO_T_TIME_EN),
- .ODT_WIDTH (ODT_WIDTH),
- .ROW_WIDTH (ROW_WIDTH),
- .DDR_TYPE (DDR_TYPE)
- )
- u_phy_ctl_io
- (
- .clk0 (clk0),
- .clk90 (clk90),
- .rst0 (rst0),
- .rst90 (rst90),
- .ctrl_addr (ctrl_addr),
- .ctrl_ba (ctrl_ba),
- .ctrl_ras_n (ctrl_ras_n),
- .ctrl_cas_n (ctrl_cas_n),
- .ctrl_we_n (ctrl_we_n),
- .ctrl_cs_n (ctrl_cs_n),
- .phy_init_addr (phy_init_addr),
- .phy_init_ba (phy_init_ba),
- .phy_init_ras_n (phy_init_ras_n),
- .phy_init_cas_n (phy_init_cas_n),
- .phy_init_we_n (phy_init_we_n),
- .phy_init_cs_n (phy_init_cs_n),
- .phy_init_cke (phy_init_cke),
- .phy_init_data_sel (phy_init_data_sel),
- .odt (odt),
- .ddr_addr (ddr_addr),
- .ddr_ba (ddr_ba),
- .ddr_ras_n (ddr_ras_n),
- .ddr_cas_n (ddr_cas_n),
- .ddr_we_n (ddr_we_n),
- .ddr_cke (ddr_cke),
- .ddr_cs_n (ddr_cs_n),
- .ddr_odt (ddr_odt)
- );
-
- ddr2_phy_init #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .CKE_WIDTH (CKE_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .CS_BITS (CS_BITS),
- .CS_NUM (CS_NUM),
- .DQ_WIDTH (DQ_WIDTH),
- .ODT_WIDTH (ODT_WIDTH),
- .ROW_WIDTH (ROW_WIDTH),
- .ADDITIVE_LAT (ADDITIVE_LAT),
- .BURST_LEN (BURST_LEN),
- .BURST_TYPE (BURST_TYPE),
- .TWO_T_TIME_EN(TWO_T_TIME_EN),
- .CAS_LAT (CAS_LAT),
- .ODT_TYPE (ODT_TYPE),
- .REDUCE_DRV (REDUCE_DRV),
- .REG_ENABLE (REG_ENABLE),
- .TWR (TWR),
- .CLK_PERIOD (CLK_PERIOD),
- .DDR_TYPE (DDR_TYPE),
- .SIM_ONLY (SIM_ONLY)
- )
- u_phy_init
- (
- .clk0 (clk0),
- .clkdiv0 (clkdiv0),
- .rst0 (rst0),
- .rstdiv0 (rstdiv0),
- .calib_done (calib_done),
- .ctrl_ref_flag (ctrl_ref_flag),
- .calib_ref_req (calib_ref_req),
- .calib_start (calib_start),
- .calib_ref_done (calib_ref_done),
- .phy_init_wren (phy_init_wren),
- .phy_init_rden (phy_init_rden),
- .phy_init_addr (phy_init_addr),
- .phy_init_ba (phy_init_ba),
- .phy_init_ras_n (phy_init_ras_n),
- .phy_init_cas_n (phy_init_cas_n),
- .phy_init_we_n (phy_init_we_n),
- .phy_init_cs_n (phy_init_cs_n),
- .phy_init_cke (phy_init_cke),
- .phy_init_done (phy_init_done),
- .phy_init_data_sel (phy_init_data_sel)
- );
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_init.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_init.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_init.v (nonexistent)
@@ -1,1219 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_phy_init.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Thu Aug 24 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-//Reference:
-// This module is the intialization control logic of the memory interface.
-// All commands are issued from here acoording to the burst, CAS Latency and
-// the user commands.
-//Revision History:
-// Rev 1.1 - Localparam WR_RECOVERY added and mapped to
-// load mode register. PK. 14/7/08
-// Rev 1.2 - To issue an Auto Refresh command to each chip during various
-// calibration stages logic modified. PK. 08/10/08
-// Rev 1.3 - Retain current data pattern for stage 4 calibration, and create
-// new pattern for stage 4. RC. 09/21/09.
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_phy_init #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter CKE_WIDTH = 1,
- parameter COL_WIDTH = 10,
- parameter CS_BITS = 0,
- parameter CS_NUM = 1,
- parameter DQ_WIDTH = 72,
- parameter ODT_WIDTH = 1,
- parameter ROW_WIDTH = 14,
- parameter ADDITIVE_LAT = 0,
- parameter BURST_LEN = 4,
- parameter TWO_T_TIME_EN = 0,
- parameter BURST_TYPE = 0,
- parameter CAS_LAT = 5,
- parameter ODT_TYPE = 1,
- parameter REDUCE_DRV = 0,
- parameter REG_ENABLE = 1,
- parameter TWR = 15000,
- parameter CLK_PERIOD = 3000,
- parameter DDR_TYPE = 1,
- parameter SIM_ONLY = 0
- )
- (
- input clk0,
- input clkdiv0,
- input rst0,
- input rstdiv0,
- input [3:0] calib_done,
- input ctrl_ref_flag,
- input calib_ref_req,
- output reg [3:0] calib_start,
- output reg calib_ref_done,
- output reg phy_init_wren,
- output reg phy_init_rden,
- output [ROW_WIDTH-1:0] phy_init_addr,
- output [BANK_WIDTH-1:0] phy_init_ba,
- output phy_init_ras_n,
- output phy_init_cas_n,
- output phy_init_we_n,
- output [CS_NUM-1:0] phy_init_cs_n,
- output [CKE_WIDTH-1:0] phy_init_cke,
- output reg phy_init_done,
- output phy_init_data_sel
- );
-
- // time to wait between consecutive commands in PHY_INIT - this is a
- // generic number, and must be large enough to account for worst case
- // timing parameter (tRFC - refresh-to-active) across all memory speed
- // grades and operating frequencies. Expressed in CLKDIV clock cycles.
- localparam CNTNEXT_CMD = 7'b1111111;
- // time to wait between read and read or precharge for stage 3 & 4
- // the larger CNTNEXT_CMD can also be used, use smaller number to
- // speed up calibration - avoid tRAS violation, and speeds up simulation
- localparam CNTNEXT_RD = 4'b1111;
-
- // Write recovery (WR) time - is defined by
- // tWR (in nanoseconds) by tCK (in nanoseconds) and rounding up a
- // noninteger value to the next integer
- localparam integer WR_RECOVERY = ((TWR + CLK_PERIOD) - 1)/CLK_PERIOD;
- localparam CS_BITS_FIX = (CS_BITS == 0) ? 1 : CS_BITS;
-
- localparam INIT_CAL1_READ = 5'h00;
- localparam INIT_CAL2_READ = 5'h01;
- localparam INIT_CAL3_READ = 5'h02;
- localparam INIT_CAL4_READ = 5'h03;
- localparam INIT_CAL1_WRITE = 5'h04;
- localparam INIT_CAL2_WRITE = 5'h05;
- localparam INIT_CAL3_WRITE = 5'h06;
- localparam INIT_DUMMY_ACTIVE_WAIT = 5'h07;
- localparam INIT_PRECHARGE = 5'h08;
- localparam INIT_LOAD_MODE = 5'h09;
- localparam INIT_AUTO_REFRESH = 5'h0A;
- localparam INIT_IDLE = 5'h0B;
- localparam INIT_CNT_200 = 5'h0C;
- localparam INIT_CNT_200_WAIT = 5'h0D;
- localparam INIT_PRECHARGE_WAIT = 5'h0E;
- localparam INIT_MODE_REGISTER_WAIT = 5'h0F;
- localparam INIT_AUTO_REFRESH_WAIT = 5'h10;
- localparam INIT_DEEP_MEMORY_ST = 5'h11;
- localparam INIT_DUMMY_ACTIVE = 5'h12;
- localparam INIT_CAL1_WRITE_READ = 5'h13;
- localparam INIT_CAL1_READ_WAIT = 5'h14;
- localparam INIT_CAL2_WRITE_READ = 5'h15;
- localparam INIT_CAL2_READ_WAIT = 5'h16;
- localparam INIT_CAL3_WRITE_READ = 5'h17;
- localparam INIT_CAL3_READ_WAIT = 5'h18;
- localparam INIT_CAL4_READ_WAIT = 5'h19;
- localparam INIT_CALIB_REF = 5'h1A;
- localparam INIT_ZQCL = 5'h1B;
- localparam INIT_WAIT_DLLK_ZQINIT = 5'h1C;
- localparam INIT_CAL4_WRITE = 5'h1D; // MIG 3.3: New state
- localparam INIT_CAL4_WRITE_READ = 5'h1E; // MIG 3.3: New state
-
- localparam INIT_CNTR_INIT = 4'h0;
- localparam INIT_CNTR_PRECH_1 = 4'h1;
- localparam INIT_CNTR_EMR2_INIT = 4'h2;
- localparam INIT_CNTR_EMR3_INIT = 4'h3;
- localparam INIT_CNTR_EMR_EN_DLL = 4'h4;
- localparam INIT_CNTR_MR_RST_DLL = 4'h5;
- localparam INIT_CNTR_CNT_200_WAIT = 4'h6;
- localparam INIT_CNTR_PRECH_2 = 4'h7;
- localparam INIT_CNTR_AR_1 = 4'h8;
- localparam INIT_CNTR_AR_2 = 4'h9;
- localparam INIT_CNTR_MR_ACT_DLL = 4'hA;
- localparam INIT_CNTR_EMR_DEF_OCD = 4'hB;
- localparam INIT_CNTR_EMR_EXIT_OCD = 4'hC;
- localparam INIT_CNTR_DEEP_MEM = 4'hD;
- // MIG 3.3: Remove extra precharge occurring at end of calibration
-// localparam INIT_CNTR_PRECH_3 = 4'hE;
-// localparam INIT_CNTR_DONE = 4'hF;
- localparam INIT_CNTR_DONE = 4'hE;
-
- localparam DDR1 = 0;
- localparam DDR2 = 1;
- localparam DDR3 = 2;
-
- reg [CS_BITS_FIX :0] auto_cnt_r;
- reg [1:0] burst_addr_r;
- reg [1:0] burst_cnt_r;
- wire [1:0] burst_val;
- wire cal_read;
- wire cal_write;
- wire cal_write_read;
- reg cal1_started_r;
- reg cal2_started_r;
- reg cal4_started_r;
- reg [3:0] calib_done_r;
- reg calib_ref_req_posedge;
- reg calib_ref_req_r;
- reg [15:0] calib_start_shift0_r;
- reg [15:0] calib_start_shift1_r;
- reg [15:0] calib_start_shift2_r;
- reg [15:0] calib_start_shift3_r;
- reg [1:0] chip_cnt_r;
- reg [4:0] cke_200us_cnt_r;
- reg cke_200us_cnt_en_r;
- reg [7:0] cnt_200_cycle_r;
- reg cnt_200_cycle_done_r;
- reg [6:0] cnt_cmd_r;
- reg cnt_cmd_ok_r;
- reg [3:0] cnt_rd_r;
- reg cnt_rd_ok_r;
- reg ctrl_ref_flag_r;
- reg done_200us_r;
- reg [ROW_WIDTH-1:0] ddr_addr_r;
- reg [ROW_WIDTH-1:0] ddr_addr_r1;
- reg [BANK_WIDTH-1:0] ddr_ba_r;
- reg [BANK_WIDTH-1:0] ddr_ba_r1;
- reg ddr_cas_n_r;
- reg ddr_cas_n_r1;
- reg [CKE_WIDTH-1:0] ddr_cke_r;
- reg [CS_NUM-1:0] ddr_cs_n_r;
- reg [CS_NUM-1:0] ddr_cs_n_r1;
- reg [CS_NUM-1:0] ddr_cs_disable_r;
- reg ddr_ras_n_r;
- reg ddr_ras_n_r1;
- reg ddr_we_n_r;
- reg ddr_we_n_r1;
- wire [15:0] ext_mode_reg;
- reg [3:0] init_cnt_r;
- reg init_done_r;
- reg [4:0] init_next_state;
- reg [4:0] init_state_r;
- reg [4:0] init_state_r1;
- reg [4:0] init_state_r1_2t;
- reg [4:0] init_state_r2;
- wire [15:0] load_mode_reg;
- wire [15:0] load_mode_reg0;
- wire [15:0] load_mode_reg1;
- wire [15:0] load_mode_reg2;
- wire [15:0] load_mode_reg3;
- reg phy_init_done_r;
- reg phy_init_done_r1;
- reg phy_init_done_r2;
- reg phy_init_done_r3;
- reg refresh_req;
- wire [3:0] start_cal;
-
- //***************************************************************************
-
- //*****************************************************************
- // DDR1 and DDR2 Load mode register
- // Mode Register (MR):
- // [15:14] - unused - 00
- // [13] - reserved - 0
- // [12] - Power-down mode - 0 (normal)
- // [11:9] - write recovery - for Auto Precharge (tWR/tCK)
- // [8] - DLL reset - 0 or 1
- // [7] - Test Mode - 0 (normal)
- // [6:4] - CAS latency - CAS_LAT
- // [3] - Burst Type - BURST_TYPE
- // [2:0] - Burst Length - BURST_LEN
- //*****************************************************************
-
- generate
- if (DDR_TYPE == DDR2) begin: gen_load_mode_reg_ddr2
- assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
- ((BURST_LEN == 4) ? 3'b010 : 3'b111);
- assign load_mode_reg[3] = BURST_TYPE;
- assign load_mode_reg[6:4] = (CAS_LAT == 3) ? 3'b011 :
- ((CAS_LAT == 4) ? 3'b100 :
- ((CAS_LAT == 5) ? 3'b101 : 3'b111));
- assign load_mode_reg[7] = 1'b0;
- assign load_mode_reg[8] = 1'b0; // init value only (DLL not reset)
- assign load_mode_reg[11:9] = (WR_RECOVERY == 6) ? 3'b101 :
- ((WR_RECOVERY == 5) ? 3'b100 :
- ((WR_RECOVERY == 4) ? 3'b011 :
- ((WR_RECOVERY == 3) ? 3'b010 :
- 3'b001)));
- assign load_mode_reg[15:12] = 4'b000;
- end else if (DDR_TYPE == DDR1)begin: gen_load_mode_reg_ddr1
- assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
- ((BURST_LEN == 4) ? 3'b010 :
- ((BURST_LEN == 2) ? 3'b001 : 3'b111));
- assign load_mode_reg[3] = BURST_TYPE;
- assign load_mode_reg[6:4] = (CAS_LAT == 2) ? 3'b010 :
- ((CAS_LAT == 3) ? 3'b011 :
- ((CAS_LAT == 25) ? 3'b110 : 3'b111));
- assign load_mode_reg[12:7] = 6'b000000; // init value only
- assign load_mode_reg[15:13] = 3'b000;
- end
- endgenerate
-
- //*****************************************************************
- // DDR1 and DDR2 ext mode register
- // Extended Mode Register (MR):
- // [15:14] - unused - 00
- // [13] - reserved - 0
- // [12] - output enable - 0 (enabled)
- // [11] - RDQS enable - 0 (disabled)
- // [10] - DQS# enable - 0 (enabled)
- // [9:7] - OCD Program - 111 or 000 (first 111, then 000 during init)
- // [6] - RTT[1] - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
- // [5:3] - Additive CAS - ADDITIVE_CAS
- // [2] - RTT[0]
- // [1] - Output drive - REDUCE_DRV (= 0(full), = 1 (reduced)
- // [0] - DLL enable - 0 (normal)
- //*****************************************************************
-
- generate
- if (DDR_TYPE == DDR2) begin: gen_ext_mode_reg_ddr2
- assign ext_mode_reg[0] = 1'b0;
- assign ext_mode_reg[1] = REDUCE_DRV;
- assign ext_mode_reg[2] = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
- 1'b1 : 1'b0;
- assign ext_mode_reg[5:3] = (ADDITIVE_LAT == 0) ? 3'b000 :
- ((ADDITIVE_LAT == 1) ? 3'b001 :
- ((ADDITIVE_LAT == 2) ? 3'b010 :
- ((ADDITIVE_LAT == 3) ? 3'b011 :
- ((ADDITIVE_LAT == 4) ? 3'b100 :
- 3'b111))));
- assign ext_mode_reg[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
- 1'b1 : 1'b0;
- assign ext_mode_reg[9:7] = 3'b000;
- assign ext_mode_reg[10] = 1'b0;
- assign ext_mode_reg[15:10] = 6'b000000;
- end else if (DDR_TYPE == DDR1) begin: gen_ext_mode_reg_ddr1
- assign ext_mode_reg[0] = 1'b0;
- assign ext_mode_reg[1] = REDUCE_DRV;
- assign ext_mode_reg[12:2] = 11'b00000000000;
- assign ext_mode_reg[15:13] = 3'b000;
- end
- endgenerate
-
- //*****************************************************************
- // DDR3 Load mode reg0
- // Mode Register (MR0):
- // [15:13] - unused - 000
- // [12] - Precharge Power-down DLL usage - 0 (DLL frozen, slow-exit),
- // 1 (DLL maintained)
- // [11:9] - write recovery for Auto Precharge (tWR/tCK = 6)
- // [8] - DLL reset - 0 or 1
- // [7] - Test Mode - 0 (normal)
- // [6:4],[2] - CAS latency - CAS_LAT
- // [3] - Burst Type - BURST_TYPE
- // [1:0] - Burst Length - BURST_LEN
- //*****************************************************************
-
- generate
- if (DDR_TYPE == DDR3) begin: gen_load_mode_reg0_ddr3
- assign load_mode_reg0[1:0] = (BURST_LEN == 8) ? 2'b00 :
- ((BURST_LEN == 4) ? 2'b10 : 2'b11);
- // Part of CAS latency. This bit is '0' for all CAS latencies
- assign load_mode_reg0[2] = 1'b0;
- assign load_mode_reg0[3] = BURST_TYPE;
- assign load_mode_reg0[6:4] = (CAS_LAT == 5) ? 3'b001 :
- (CAS_LAT == 6) ? 3'b010 : 3'b111;
- assign load_mode_reg0[7] = 1'b0;
- // init value only (DLL reset)
- assign load_mode_reg0[8] = 1'b1;
- assign load_mode_reg0[11:9] = 3'b010;
- // Precharge Power-Down DLL 'slow-exit'
- assign load_mode_reg0[12] = 1'b0;
- assign load_mode_reg0[15:13] = 3'b000;
- end
- endgenerate
-
- //*****************************************************************
- // DDR3 Load mode reg1
- // Mode Register (MR1):
- // [15:13] - unused - 00
- // [12] - output enable - 0 (enabled for DQ, DQS, DQS#)
- // [11] - TDQS enable - 0 (TDQS disabled and DM enabled)
- // [10] - reserved - 0 (must be '0')
- // [9] - RTT[2] - 0
- // [8] - reserved - 0 (must be '0')
- // [7] - write leveling - 0 (disabled), 1 (enabled)
- // [6] - RTT[1] - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
- // [5] - Output driver impedance[1] - 0 (RZQ/6 and RZQ/7)
- // [4:3] - Additive CAS - ADDITIVE_CAS
- // [2] - RTT[0]
- // [1] - Output driver impedance[0] - 0(RZQ/6), or 1 (RZQ/7)
- // [0] - DLL enable - 0 (normal)
- //*****************************************************************
-
- generate
- if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg1_ddr3
- // DLL enabled during Imitialization
- assign load_mode_reg1[0] = 1'b0;
- // RZQ/6
- assign load_mode_reg1[1] = REDUCE_DRV;
- assign load_mode_reg1[2] = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
- 1'b1 : 1'b0;
- assign load_mode_reg1[4:3] = (ADDITIVE_LAT == 0) ? 2'b00 :
- ((ADDITIVE_LAT == 1) ? 2'b01 :
- ((ADDITIVE_LAT == 2) ? 2'b10 :
- 3'b111));
- // RZQ/6
- assign load_mode_reg1[5] = 1'b0;
- assign load_mode_reg1[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
- 1'b1 : 1'b0;
- // Make zero WRITE_LEVEL
- assign load_mode_reg1[7] = 0;
- assign load_mode_reg1[8] = 1'b0;
- assign load_mode_reg1[9] = 1'b0;
- assign load_mode_reg1[10] = 1'b0;
- assign load_mode_reg1[15:11] = 5'b00000;
- end
- endgenerate
-
- //*****************************************************************
- // DDR3 Load mode reg2
- // Mode Register (MR2):
- // [15:11] - unused - 00
- // [10:9] - RTT_WR - 00 (Dynamic ODT off)
- // [8] - reserved - 0 (must be '0')
- // [7] - self-refresh temperature range -
- // 0 (normal), 1 (extended)
- // [6] - Auto Self-Refresh - 0 (manual), 1(auto)
- // [5:3] - CAS Write Latency (CWL) -
- // 000 (5 for 400 MHz device),
- // 001 (6 for 400 MHz to 533 MHz devices),
- // 010 (7 for 533 MHz to 667 MHz devices),
- // 011 (8 for 667 MHz to 800 MHz)
- // [2:0] - Partial Array Self-Refresh (Optional) -
- // 000 (full array)
- //*****************************************************************
-
- generate
- if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg2_ddr3
- assign load_mode_reg2[2:0] = 3'b000;
- assign load_mode_reg2[5:3] = (CAS_LAT == 5) ? 3'b000 :
- (CAS_LAT == 6) ? 3'b001 : 3'b111;
- assign load_mode_reg2[6] = 1'b0; // Manual Self-Refresh
- assign load_mode_reg2[7] = 1'b0;
- assign load_mode_reg2[8] = 1'b0;
- assign load_mode_reg2[10:9] = 2'b00;
- assign load_mode_reg2[15:11] = 5'b00000;
- end
- endgenerate
-
- //*****************************************************************
- // DDR3 Load mode reg3
- // Mode Register (MR3):
- // [15:3] - unused - All zeros
- // [2] - MPR Operation - 0(normal operation), 1(data flow from MPR)
- // [1:0] - MPR location - 00 (Predefined pattern)
- //*****************************************************************
-
- generate
- if (DDR_TYPE == DDR3)begin: gen_ext_mode_reg3_ddr3
- assign load_mode_reg3[1:0] = 2'b00;
- assign load_mode_reg3[2] = 1'b0;
- assign load_mode_reg3[15:3] = 13'b0000000000000;
- end
- endgenerate
-
- //***************************************************************************
- // Logic for calibration start, and for auto-refresh during cal request
- // CALIB_REF_REQ is used by calibration logic to request auto-refresh
- // durign calibration (used to avoid tRAS violation is certain calibration
- // stages take a long time). Once the auto-refresh is complete and cal can
- // be resumed, CALIB_REF_DONE is asserted by PHY_INIT.
- //***************************************************************************
-
- // generate pulse for each of calibration start controls
- assign start_cal[0] = ((init_state_r1 == INIT_CAL1_READ) &&
- (init_state_r2 != INIT_CAL1_READ));
- assign start_cal[1] = ((init_state_r1 == INIT_CAL2_READ) &&
- (init_state_r2 != INIT_CAL2_READ));
- assign start_cal[2] = ((init_state_r1 == INIT_CAL3_READ) &&
- (init_state_r2 == INIT_CAL3_WRITE_READ));
- assign start_cal[3] = ((init_state_r1 == INIT_CAL4_READ) &&
- (init_state_r2 != INIT_CAL4_READ));
- // MIG 3.3: Change to accomodate FSM changes related to stage 4 calibration
-// (init_state_r2 == INIT_CAL4_WRITE_READ));
-
- // Generate positive-edge triggered, latched signal to force initialization
- // to pause calibration, and to issue auto-refresh. Clear flag as soon as
- // refresh initiated
- always @(posedge clkdiv0)
- if (rstdiv0) begin
- calib_ref_req_r <= 1'b0;
- calib_ref_req_posedge <= 1'b0;
- refresh_req <= 1'b0;
- end else begin
- calib_ref_req_r <= calib_ref_req;
- calib_ref_req_posedge <= calib_ref_req & ~calib_ref_req_r;
- if (init_state_r1 == INIT_AUTO_REFRESH)
- refresh_req <= 1'b0;
- else if (calib_ref_req_posedge)
- refresh_req <= 1'b1;
- end
-
- // flag to tell cal1 calibration was started.
- // This flag is used for cal1 auto refreshes
- // some of these bits may not be needed - only needed for those stages that
- // need refreshes within the stage (i.e. very long stages)
- always @(posedge clkdiv0)
- if (rstdiv0) begin
- cal1_started_r <= 1'b0;
- cal2_started_r <= 1'b0;
- cal4_started_r <= 1'b0;
- end else begin
- if (calib_start[0])
- cal1_started_r <= 1'b1;
- if (calib_start[1])
- cal2_started_r <= 1'b1;
- if (calib_start[3])
- cal4_started_r <= 1'b1;
- end
-
- // Delay start of each calibration by 16 clock cycles to
- // ensure that when calibration logic begins, that read data is already
- // appearing on the bus. Don't really need it, it's more for simulation
- // purposes. Each circuit should synthesize using an SRL16.
- // In first stage of calibration periodic auto refreshes
- // will be issued to meet memory timing. calib_start_shift0_r[15] will be
- // asserted more than once.calib_start[0] is anded with cal1_started_r so
- // that it is asserted only once. cal1_refresh_done is anded with
- // cal1_started_r so that it is asserted after the auto refreshes.
- always @(posedge clkdiv0) begin
- calib_start_shift0_r <= {calib_start_shift0_r[14:0], start_cal[0]};
- calib_start_shift1_r <= {calib_start_shift1_r[14:0], start_cal[1]};
- calib_start_shift2_r <= {calib_start_shift2_r[14:0], start_cal[2]};
- calib_start_shift3_r <= {calib_start_shift3_r[14:0], start_cal[3]};
- calib_start[0] <= calib_start_shift0_r[15] & ~cal1_started_r;
- calib_start[1] <= calib_start_shift1_r[15] & ~cal2_started_r;
- calib_start[2] <= calib_start_shift2_r[15];
- calib_start[3] <= calib_start_shift3_r[15] & ~cal4_started_r;
- calib_ref_done <= calib_start_shift0_r[15] |
- calib_start_shift1_r[15] |
- calib_start_shift3_r[15];
- end
-
- // generate delay for various states that require it (no maximum delay
- // requirement, make sure that terminal count is large enough to cover
- // all cases)
- always @(posedge clkdiv0) begin
- case (init_state_r)
- INIT_PRECHARGE_WAIT,
- INIT_MODE_REGISTER_WAIT,
- INIT_AUTO_REFRESH_WAIT,
- INIT_DUMMY_ACTIVE_WAIT,
- INIT_CAL1_WRITE_READ,
- INIT_CAL1_READ_WAIT,
- INIT_CAL2_WRITE_READ,
- INIT_CAL2_READ_WAIT,
- INIT_CAL3_WRITE_READ,
- INIT_CAL4_WRITE_READ :
- cnt_cmd_r <= cnt_cmd_r + 1;
- default:
- cnt_cmd_r <= 7'b0000000;
- endcase
- end
-
- // assert when count reaches the value
- always @(posedge clkdiv0) begin
- if(cnt_cmd_r == CNTNEXT_CMD)
- cnt_cmd_ok_r <= 1'b1;
- else
- cnt_cmd_ok_r <= 1'b0;
- end
-
- always @(posedge clkdiv0) begin
- case (init_state_r)
- INIT_CAL3_READ_WAIT,
- INIT_CAL4_READ_WAIT:
- cnt_rd_r <= cnt_rd_r + 1;
- default:
- cnt_rd_r <= 4'b0000;
- endcase
- end
-
- always @(posedge clkdiv0) begin
- if(cnt_rd_r == CNTNEXT_RD)
- cnt_rd_ok_r <= 1'b1;
- else
- cnt_rd_ok_r <= 1'b0;
- end
-
- //***************************************************************************
- // Initial delay after power-on
- //***************************************************************************
-
- // register the refresh flag from the controller.
- // The refresh flag is in full frequency domain - so a pulsed version must
- // be generated for half freq domain using 2 consecutive full clk cycles
- // The registered version is used for the 200us counter
- always @(posedge clk0)
- ctrl_ref_flag_r <= ctrl_ref_flag;
- always @(posedge clkdiv0)
- cke_200us_cnt_en_r <= ctrl_ref_flag || ctrl_ref_flag_r;
-
- // 200us counter for cke
- always @(posedge clkdiv0)
- if (rstdiv0) begin
- // skip power-up count if only simulating
- if (SIM_ONLY)
- cke_200us_cnt_r <= 5'b00001;
- else
- cke_200us_cnt_r <= 5'd27;
- end else if (cke_200us_cnt_en_r)
- cke_200us_cnt_r <= cke_200us_cnt_r - 1;
-
- always @(posedge clkdiv0)
- if (rstdiv0)
- done_200us_r <= 1'b0;
- else if (!done_200us_r)
- done_200us_r <= (cke_200us_cnt_r == 5'b00000);
-
- // 200 clocks counter - count value : h'64 required for initialization
- // Counts 100 divided by two clocks
- always @(posedge clkdiv0)
- if (rstdiv0 || (init_state_r == INIT_CNT_200))
- cnt_200_cycle_r <= 8'h64;
- else if (init_state_r == INIT_ZQCL) // ddr3
- cnt_200_cycle_r <= 8'hC8;
- else if (cnt_200_cycle_r != 8'h00)
- cnt_200_cycle_r <= cnt_200_cycle_r - 1;
-
- always @(posedge clkdiv0)
- if (rstdiv0 || (init_state_r == INIT_CNT_200)
- || (init_state_r == INIT_ZQCL))
- cnt_200_cycle_done_r <= 1'b0;
- else if (cnt_200_cycle_r == 8'h00)
- cnt_200_cycle_done_r <= 1'b1;
-
- //*****************************************************************
- // handle deep memory configuration:
- // During initialization: Repeat initialization sequence once for each
- // chip select. Note that we could perform initalization for all chip
- // selects simulataneously. Probably fine - any potential SI issues with
- // auto refreshing all chip selects at once?
- // Once initialization complete, assert only CS[1] for calibration.
- //*****************************************************************
-
- always @(posedge clkdiv0)
- if (rstdiv0) begin
- chip_cnt_r <= 2'b00;
- end else if (init_state_r == INIT_DEEP_MEMORY_ST) begin
- if (chip_cnt_r != CS_NUM)
- chip_cnt_r <= chip_cnt_r + 1;
- else
- chip_cnt_r <= 2'b00;
- // MIG 2.4: Modified to issue an Auto Refresh commmand
- // to each chip select during various calibration stages
- end else if (init_state_r == INIT_PRECHARGE && init_done_r) begin
- chip_cnt_r <= 2'b00;
- end else if (init_state_r1 == INIT_AUTO_REFRESH && init_done_r) begin
- if (chip_cnt_r < (CS_NUM-1))
- chip_cnt_r <= chip_cnt_r + 1;
- end
-
- // keep track of which chip selects got auto-refreshed (avoid auto-refreshing
- // all CS's at once to avoid current spike)
- always @(posedge clkdiv0)begin
- if (rstdiv0 || init_state_r == INIT_PRECHARGE)
- auto_cnt_r <= 'd0;
- else if (init_state_r == INIT_AUTO_REFRESH && init_done_r) begin
- if (auto_cnt_r < CS_NUM)
- auto_cnt_r <= auto_cnt_r + 1;
- end
- end
-
- always @(posedge clkdiv0)
- if (rstdiv0) begin
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- end else begin
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- if ((init_state_r == INIT_DUMMY_ACTIVE) ||
- ((init_state_r == INIT_PRECHARGE) && (~init_done_r))||
- (init_state_r == INIT_LOAD_MODE) ||
- (init_state_r == INIT_AUTO_REFRESH) ||
- (init_state_r == INIT_ZQCL ) ||
- (((init_state_r == INIT_CAL1_READ) ||
- (init_state_r == INIT_CAL2_READ) ||
- (init_state_r == INIT_CAL3_READ) ||
- (init_state_r == INIT_CAL4_READ) ||
- (init_state_r == INIT_CAL1_WRITE) ||
- (init_state_r == INIT_CAL2_WRITE) ||
- (init_state_r == INIT_CAL3_WRITE) ||
- (init_state_r == INIT_CAL4_WRITE)) && (burst_cnt_r == 2'b00)))
- ddr_cs_n_r[chip_cnt_r] <= 1'b0;
- else if (init_state_r == INIT_PRECHARGE)
- ddr_cs_n_r <= {CS_NUM{1'b0}};
- else
- ddr_cs_n_r[chip_cnt_r] <= 1'b1;
- end
-
- //***************************************************************************
- // Write/read burst logic
- //***************************************************************************
-
- assign cal_write = ((init_state_r == INIT_CAL1_WRITE) ||
- (init_state_r == INIT_CAL2_WRITE) ||
- (init_state_r == INIT_CAL3_WRITE) ||
- (init_state_r == INIT_CAL4_WRITE));
- assign cal_read = ((init_state_r == INIT_CAL1_READ) ||
- (init_state_r == INIT_CAL2_READ) ||
- (init_state_r == INIT_CAL3_READ) ||
- (init_state_r == INIT_CAL4_READ));
- assign cal_write_read = ((init_state_r == INIT_CAL1_READ) ||
- (init_state_r == INIT_CAL2_READ) ||
- (init_state_r == INIT_CAL3_READ) ||
- (init_state_r == INIT_CAL4_READ) ||
- (init_state_r == INIT_CAL1_WRITE) ||
- (init_state_r == INIT_CAL2_WRITE) ||
- (init_state_r == INIT_CAL3_WRITE) ||
- (init_state_r == INIT_CAL4_WRITE));
-
- assign burst_val = (BURST_LEN == 4) ? 2'b00 :
- (BURST_LEN == 8) ? 2'b01 : 2'b00;
-
- // keep track of current address - need this if burst length < 8 for
- // stage 2-4 calibration writes and reads. Make sure value always gets
- // initialized to 0 before we enter write/read state. This is used to
- // keep track of when another burst must be issued
- always @(posedge clkdiv0)
- if (cal_write_read)
- burst_addr_r <= burst_addr_r + 2;
- else
- burst_addr_r <= 2'b00;
-
- // write/read burst count
- always @(posedge clkdiv0)
- if (cal_write_read)
- if (burst_cnt_r == 2'b00)
- burst_cnt_r <= burst_val;
- else // SHOULD THIS BE -2 CHECK THIS LOGIC
- burst_cnt_r <= burst_cnt_r - 1;
- else
- burst_cnt_r <= 2'b00;
-
- // indicate when a write is occurring
- always @(posedge clkdiv0)
- // MIG 2.1: Remove (burst_addr_r<4) term - not used
- // phy_init_wren <= cal_write && (burst_addr_r < 3'd4);
- phy_init_wren <= cal_write;
-
- // used for read enable calibration, pulse to indicate when read issued
- always @(posedge clkdiv0)
- // MIG 2.1: Remove (burst_addr_r<4) term - not used
- // phy_init_rden <= cal_read && (burst_addr_r < 3'd4);
- phy_init_rden <= cal_read;
-
- //***************************************************************************
- // Initialization state machine
- //***************************************************************************
-
- always @(posedge clkdiv0)
- // every time we need to initialize another rank of memory, need to
- // reset init count, and repeat the entire initialization (but not
- // calibration) sequence
- if (rstdiv0 || (init_state_r == INIT_DEEP_MEMORY_ST))
- init_cnt_r <= INIT_CNTR_INIT;
- else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_PRECHARGE) &&
- (init_cnt_r == INIT_CNTR_PRECH_1))
- // skip EMR(2) and EMR(3) register loads
- init_cnt_r <= INIT_CNTR_EMR_EN_DLL;
- else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_LOAD_MODE) &&
- (init_cnt_r == INIT_CNTR_MR_ACT_DLL))
- // skip OCD calibration for DDR1
- init_cnt_r <= INIT_CNTR_DEEP_MEM;
- else if ((DDR_TYPE == DDR3) && (init_state_r == INIT_ZQCL))
- // skip states for DDR3
- init_cnt_r <= INIT_CNTR_DEEP_MEM;
- else if ((init_state_r == INIT_LOAD_MODE) ||
- ((init_state_r == INIT_PRECHARGE) &&
- (init_state_r1 != INIT_CALIB_REF)) ||
- ((init_state_r == INIT_AUTO_REFRESH) && (~init_done_r)) ||
- (init_state_r == INIT_CNT_200) ||
- // MIG 3.3: Added increment when starting calibration
- ((init_state_r == INIT_DUMMY_ACTIVE) &&
- (init_state_r1 == INIT_IDLE)))
- init_cnt_r <= init_cnt_r + 1;
-
- always @(posedge clkdiv0) begin
- if ((init_state_r == INIT_IDLE) && (init_cnt_r == INIT_CNTR_DONE)) begin
- phy_init_done_r <= 1'b1;
- end else
- phy_init_done_r <= 1'b0;
- end
-
- // phy_init_done to the controller and the user interface.
- // It is delayed by four clocks to account for the
- // multi cycle path constraint to the (phy_init_data_sel)
- // to the phy layer.
- always @(posedge clkdiv0) begin
- phy_init_done_r1 <= phy_init_done_r;
- phy_init_done_r2 <= phy_init_done_r1;
- phy_init_done_r3 <= phy_init_done_r2;
- phy_init_done <= phy_init_done_r3;
- end
-
- // Instantiate primitive to allow this flop to be attached to multicycle
- // path constraint in UCF. This signal goes to PHY_WRITE and PHY_CTL_IO
- // datapath logic only. Because it is a multi-cycle path, it can be
- // clocked by either CLKDIV0 or CLK0.
- FDRSE u_ff_phy_init_data_sel
- (
- .Q (phy_init_data_sel),
- .C (clkdiv0),
- .CE (1'b1),
- .D (phy_init_done_r1),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve=1 */
- /* synthesis syn_replicate = 0 */;
-
- //synthesis translate_off
- always @(posedge calib_done[0])
- $display ("First Stage Calibration completed at time %t", $time);
-
- always @(posedge calib_done[1])
- $display ("Second Stage Calibration completed at time %t", $time);
-
- always @(posedge calib_done[2]) begin
- $display ("Third Stage Calibration completed at time %t", $time);
- end
-
- always @(posedge calib_done[3]) begin
- $display ("Fourth Stage Calibration completed at time %t", $time);
- $display ("Calibration completed at time %t", $time);
- end
- //synthesis translate_on
-
- always @(posedge clkdiv0) begin
- if ((init_cnt_r >= INIT_CNTR_DEEP_MEM))begin
- init_done_r <= 1'b1;
- end else
- init_done_r <= 1'b0;
- end
-
- //*****************************************************************
-
- always @(posedge clkdiv0)
- if (rstdiv0) begin
- init_state_r <= INIT_IDLE;
- init_state_r1 <= INIT_IDLE;
- init_state_r2 <= INIT_IDLE;
- calib_done_r <= 4'b0000;
- end else begin
- init_state_r <= init_next_state;
- init_state_r1 <= init_state_r;
- init_state_r2 <= init_state_r1;
- calib_done_r <= calib_done; // register for timing
- end
-
- always @(*) begin
- init_next_state = init_state_r;
- (* full_case, parallel_case *) case (init_state_r)
- INIT_IDLE: begin
- if (done_200us_r) begin
- (* parallel_case *) case (init_cnt_r)
- INIT_CNTR_INIT:
- init_next_state = INIT_CNT_200;
- INIT_CNTR_PRECH_1:
- init_next_state = INIT_PRECHARGE;
- INIT_CNTR_EMR2_INIT:
- init_next_state = INIT_LOAD_MODE; // EMR(2)
- INIT_CNTR_EMR3_INIT:
- init_next_state = INIT_LOAD_MODE; // EMR(3);
- INIT_CNTR_EMR_EN_DLL:
- init_next_state = INIT_LOAD_MODE; // EMR, enable DLL
- INIT_CNTR_MR_RST_DLL:
- init_next_state = INIT_LOAD_MODE; // MR, reset DLL
- INIT_CNTR_CNT_200_WAIT:begin
- if(DDR_TYPE == DDR3)
- init_next_state = INIT_ZQCL; // DDR3
- else
- // Wait 200cc after reset DLL
- init_next_state = INIT_CNT_200;
- end
- INIT_CNTR_PRECH_2:
- init_next_state = INIT_PRECHARGE;
- INIT_CNTR_AR_1:
- init_next_state = INIT_AUTO_REFRESH;
- INIT_CNTR_AR_2:
- init_next_state = INIT_AUTO_REFRESH;
- INIT_CNTR_MR_ACT_DLL:
- init_next_state = INIT_LOAD_MODE; // MR, unreset DLL
- INIT_CNTR_EMR_DEF_OCD:
- init_next_state = INIT_LOAD_MODE; // EMR, OCD default
- INIT_CNTR_EMR_EXIT_OCD:
- init_next_state = INIT_LOAD_MODE; // EMR, enable OCD exit
- INIT_CNTR_DEEP_MEM: begin
- if ((chip_cnt_r < CS_NUM-1))
- init_next_state = INIT_DEEP_MEMORY_ST;
- else if (cnt_200_cycle_done_r)
- init_next_state = INIT_DUMMY_ACTIVE;
- else
- init_next_state = INIT_IDLE;
- end
- // MIG 3.3: Remove extra precharge occurring at end of calibration
-// INIT_CNTR_PRECH_3:
-// init_next_state = INIT_PRECHARGE;
- INIT_CNTR_DONE:
- init_next_state = INIT_IDLE;
- default :
- init_next_state = INIT_IDLE;
- endcase
- end
- end
- INIT_CNT_200:
- init_next_state = INIT_CNT_200_WAIT;
- INIT_CNT_200_WAIT:
- if (cnt_200_cycle_done_r)
- init_next_state = INIT_IDLE;
- INIT_PRECHARGE:
- init_next_state = INIT_PRECHARGE_WAIT;
- INIT_PRECHARGE_WAIT:
- if (cnt_cmd_ok_r)begin
- if (init_done_r && (!(&calib_done_r)))
- init_next_state = INIT_AUTO_REFRESH;
- else
- init_next_state = INIT_IDLE;
- end
- INIT_ZQCL:
- init_next_state = INIT_WAIT_DLLK_ZQINIT;
- INIT_WAIT_DLLK_ZQINIT:
- if (cnt_200_cycle_done_r)
- init_next_state = INIT_IDLE;
- INIT_LOAD_MODE:
- init_next_state = INIT_MODE_REGISTER_WAIT;
- INIT_MODE_REGISTER_WAIT:
- if (cnt_cmd_ok_r)
- init_next_state = INIT_IDLE;
- INIT_AUTO_REFRESH:
- init_next_state = INIT_AUTO_REFRESH_WAIT;
- INIT_AUTO_REFRESH_WAIT:
- // MIG 2.4: Modified to issue an Auto Refresh commmand
- // to each chip select during various calibration stages
- if (auto_cnt_r < CS_NUM && init_done_r) begin
- if (cnt_cmd_ok_r)
- init_next_state = INIT_AUTO_REFRESH;
- end else if (cnt_cmd_ok_r)begin
- if (init_done_r)
- init_next_state = INIT_DUMMY_ACTIVE;
- else
- init_next_state = INIT_IDLE;
- end
- INIT_DEEP_MEMORY_ST:
- init_next_state = INIT_IDLE;
- // single row activate. All subsequent calibration writes and
- // read will take place in this row
- INIT_DUMMY_ACTIVE:
- init_next_state = INIT_DUMMY_ACTIVE_WAIT;
- INIT_DUMMY_ACTIVE_WAIT:
- if (cnt_cmd_ok_r)begin
- if (~calib_done_r[0]) begin
- // if returning to stg1 after refresh, don't need to write
- if (cal1_started_r)
- init_next_state = INIT_CAL1_READ;
- // if first entering stg1, need to write training pattern
- else
- init_next_state = INIT_CAL1_WRITE;
- end else if (~calib_done[1]) begin
- if (cal2_started_r)
- init_next_state = INIT_CAL2_READ;
- else
- init_next_state = INIT_CAL2_WRITE;
- end else if (~calib_done_r[2])
- // Stage 3 only requires a refresh after the entire stage is
- // finished
- init_next_state = INIT_CAL3_WRITE;
- else begin
- // Stage 4 requires a refresh after every DQS group
- if (cal4_started_r)
- init_next_state = INIT_CAL4_READ;
- else
- init_next_state = INIT_CAL4_WRITE;
- end
- end
- // Stage 1 calibration (write and continuous read)
- INIT_CAL1_WRITE:
- if (burst_addr_r == 2'b10)
- init_next_state = INIT_CAL1_WRITE_READ;
- INIT_CAL1_WRITE_READ:
- if (cnt_cmd_ok_r)
- init_next_state = INIT_CAL1_READ;
- INIT_CAL1_READ:
- // Stage 1 requires inter-stage auto-refresh
- if (calib_done_r[0] || refresh_req)
- init_next_state = INIT_CAL1_READ_WAIT;
- INIT_CAL1_READ_WAIT:
- if (cnt_cmd_ok_r)
- init_next_state = INIT_CALIB_REF;
- // Stage 2 calibration (write and continuous read)
- INIT_CAL2_WRITE:
- if (burst_addr_r == 2'b10)
- init_next_state = INIT_CAL2_WRITE_READ;
- INIT_CAL2_WRITE_READ:
- if (cnt_cmd_ok_r)
- init_next_state = INIT_CAL2_READ;
- INIT_CAL2_READ:
- // Stage 2 requires inter-stage auto-refresh
- if (calib_done_r[1] || refresh_req)
- init_next_state = INIT_CAL2_READ_WAIT;
- INIT_CAL2_READ_WAIT:
- if (cnt_cmd_ok_r)
- init_next_state = INIT_CALIB_REF;
- // Stage 3 calibration (write and continuous read)
- INIT_CAL3_WRITE:
- if (burst_addr_r == 2'b10)
- init_next_state = INIT_CAL3_WRITE_READ;
- INIT_CAL3_WRITE_READ:
- if (cnt_cmd_ok_r)
- init_next_state = INIT_CAL3_READ;
- INIT_CAL3_READ:
- if (burst_addr_r == 2'b10)
- init_next_state = INIT_CAL3_READ_WAIT;
- INIT_CAL3_READ_WAIT: begin
- if (cnt_rd_ok_r)
- if (calib_done_r[2]) begin
- init_next_state = INIT_CALIB_REF;
- end else
- init_next_state = INIT_CAL3_READ;
- end
- // Stage 4 calibration
- INIT_CAL4_WRITE:
- if (burst_addr_r == 2'b10)
- init_next_state = INIT_CAL4_WRITE_READ;
- INIT_CAL4_WRITE_READ:
- if (cnt_cmd_ok_r)
- init_next_state = INIT_CAL4_READ;
- INIT_CAL4_READ:
- if (burst_addr_r == 2'b10)
- init_next_state = INIT_CAL4_READ_WAIT;
- INIT_CAL4_READ_WAIT: begin
- if (cnt_rd_ok_r)
- // Stage 4 requires inter-stage auto-refresh
- if (calib_done_r[3] || refresh_req)
- // MIG 3.3: With removal of extra precharge, proceed to
- // state CALIB_REF first to avoid incrementing init_cntr
-// init_next_state = INIT_PRECHARGE;
- init_next_state = INIT_CALIB_REF;
- else
- init_next_state = INIT_CAL4_READ;
- end
- INIT_CALIB_REF:
- init_next_state = INIT_PRECHARGE;
- endcase
- end
-
- //***************************************************************************
- // Memory control/address
- //***************************************************************************
-
- always @(posedge clkdiv0)
- if ((init_state_r == INIT_DUMMY_ACTIVE) ||
- (init_state_r == INIT_PRECHARGE) ||
- (init_state_r == INIT_LOAD_MODE) ||
- (init_state_r == INIT_AUTO_REFRESH)) begin
- ddr_ras_n_r <= 1'b0;
- end else begin
- ddr_ras_n_r <= 1'b1;
- end
-
- always @(posedge clkdiv0)
- if ((init_state_r == INIT_LOAD_MODE) ||
- (init_state_r == INIT_AUTO_REFRESH) ||
- (cal_write_read && (burst_cnt_r == 2'b00))) begin
- ddr_cas_n_r <= 1'b0;
- end else begin
- ddr_cas_n_r <= 1'b1;
- end
-
- always @(posedge clkdiv0)
- if ((init_state_r == INIT_LOAD_MODE) ||
- (init_state_r == INIT_PRECHARGE) ||
- (init_state_r == INIT_ZQCL) ||
- (cal_write && (burst_cnt_r == 2'b00)))begin
- ddr_we_n_r <= 1'b0;
- end else begin
- ddr_we_n_r <= 1'b1;
- end
-
- //*****************************************************************
- // memory address during init
- //*****************************************************************
-
- always @(posedge clkdiv0) begin
- if ((init_state_r == INIT_PRECHARGE)
- || (init_state_r == INIT_ZQCL))begin
- // Precharge all - set A10 = 1
- ddr_addr_r <= {ROW_WIDTH{1'b0}};
- ddr_addr_r[10] <= 1'b1;
- ddr_ba_r <= {BANK_WIDTH{1'b0}};
- end else if (init_state_r == INIT_LOAD_MODE) begin
- ddr_ba_r <= {BANK_WIDTH{1'b0}};
- ddr_addr_r <= {ROW_WIDTH{1'b0}};
- case (init_cnt_r)
- // EMR (2)
- INIT_CNTR_EMR2_INIT: begin
- ddr_ba_r[1:0] <= 2'b10;
- ddr_addr_r <= {ROW_WIDTH{1'b0}};
- end
- // EMR (3)
- INIT_CNTR_EMR3_INIT: begin
- ddr_ba_r[1:0] <= 2'b11;
- if(DDR_TYPE == DDR3)
- ddr_addr_r <= load_mode_reg3[ROW_WIDTH-1:0];
- else
- ddr_addr_r <= {ROW_WIDTH{1'b0}};
- end
- // EMR write - A0 = 0 for DLL enable
- INIT_CNTR_EMR_EN_DLL: begin
- ddr_ba_r[1:0] <= 2'b01;
- if(DDR_TYPE == DDR3)
- ddr_addr_r <= load_mode_reg1[ROW_WIDTH-1:0];
- else
- ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
- end
- // MR write, reset DLL (A8=1)
- INIT_CNTR_MR_RST_DLL: begin
- if(DDR_TYPE == DDR3)
- ddr_addr_r <= load_mode_reg0[ROW_WIDTH-1:0];
- else
- ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
- ddr_ba_r[1:0] <= 2'b00;
- ddr_addr_r[8] <= 1'b1;
- end
- // MR write, unreset DLL (A8=0)
- INIT_CNTR_MR_ACT_DLL: begin
- ddr_ba_r[1:0] <= 2'b00;
- ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
- end
- // EMR write, OCD default state
- INIT_CNTR_EMR_DEF_OCD: begin
- ddr_ba_r[1:0] <= 2'b01;
- ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
- ddr_addr_r[9:7] <= 3'b111;
- end
- // EMR write - OCD exit
- INIT_CNTR_EMR_EXIT_OCD: begin
- ddr_ba_r[1:0] <= 2'b01;
- ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
- end
- default: begin
- ddr_ba_r <= {BANK_WIDTH{1'bx}};
- ddr_addr_r <= {ROW_WIDTH{1'bx}};
- end
- endcase
- end else if (cal_write_read) begin
- // when writing or reading for Stages 2-4, since training pattern is
- // either 4 (stage 2) or 8 (stage 3-4) long, if BURST LEN < 8, then
- // need to issue multiple bursts to read entire training pattern
- ddr_addr_r[ROW_WIDTH-1:3] <= {ROW_WIDTH-4{1'b0}};
- ddr_addr_r[2:0] <= {burst_addr_r, 1'b0};
- ddr_ba_r <= {BANK_WIDTH-1{1'b0}};
- end else if (init_state_r == INIT_DUMMY_ACTIVE) begin
- // all calibration writing read takes place in row 0x0 only
- ddr_ba_r <= {BANK_WIDTH{1'b0}};
- ddr_addr_r <= {ROW_WIDTH{1'b0}};
- end else begin
- // otherwise, cry me a river
- ddr_ba_r <= {BANK_WIDTH{1'bx}};
- ddr_addr_r <= {ROW_WIDTH{1'bx}};
- end
- end
-
- // Keep CKE asserted after initial power-on delay
- always @(posedge clkdiv0)
- ddr_cke_r <= {CKE_WIDTH{done_200us_r}};
-
- // register commands to memory. Two clock cycle delay from state -> output
- always @(posedge clk0) begin
- ddr_addr_r1 <= ddr_addr_r;
- ddr_ba_r1 <= ddr_ba_r;
- ddr_cas_n_r1 <= ddr_cas_n_r;
- ddr_ras_n_r1 <= ddr_ras_n_r;
- ddr_we_n_r1 <= ddr_we_n_r;
- ddr_cs_n_r1 <= ddr_cs_n_r;
- end // always @ (posedge clk0)
-
- always @(posedge clk0)
- init_state_r1_2t <= init_state_r1;
-
- // logic to toggle chip select. The chip_select is
- // clocked of clkdiv0 and will be asserted for
- // two clock cycles.
- always @(posedge clk0) begin
- if(rst0)
- ddr_cs_disable_r <= {CS_NUM{1'b0}};
- else begin
- if(| ddr_cs_disable_r)
- ddr_cs_disable_r <= {CS_NUM{1'b0}};
- else begin
- if (TWO_T_TIME_EN) begin
- if (init_state_r1_2t == INIT_PRECHARGE && init_done_r)
- ddr_cs_disable_r <= 'd3;
- else
- ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r1[chip_cnt_r];
- end
- else begin
- if (init_state_r1 == INIT_PRECHARGE && init_done_r)
- ddr_cs_disable_r <= 'd3;
- else
- ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r[chip_cnt_r];
- end
- end
- end
- end
-
-
- assign phy_init_addr = ddr_addr_r;
- assign phy_init_ba = ddr_ba_r;
- assign phy_init_cas_n = ddr_cas_n_r;
- assign phy_init_cke = ddr_cke_r;
- assign phy_init_ras_n = ddr_ras_n_r;
- assign phy_init_we_n = ddr_we_n_r;
- assign phy_init_cs_n = (TWO_T_TIME_EN) ?
- ddr_cs_n_r1 | ddr_cs_disable_r
- : ddr_cs_n_r| ddr_cs_disable_r;
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_io.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_io.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_io.v (nonexistent)
@@ -1,353 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_phy_io.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module instantiates calibration logic, data, data strobe and the
-// data mask iobs.
-//Reference:
-//Revision History:
-// Rev 1.1 - DM_IOB instance made based on USE_DM_PORT value . PK. 25/6/08
-// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
-// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_phy_io #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter CLK_WIDTH = 1,
- parameter USE_DM_PORT = 1,
- parameter DM_WIDTH = 9,
- parameter DQ_WIDTH = 72,
- parameter DQ_BITS = 7,
- parameter DQ_PER_DQS = 8,
- parameter DQS_BITS = 4,
- parameter DQS_WIDTH = 9,
- parameter HIGH_PERFORMANCE_MODE = "TRUE",
- parameter IODELAY_GRP = "IODELAY_MIG",
- parameter ODT_WIDTH = 1,
- parameter ADDITIVE_LAT = 0,
- parameter CAS_LAT = 5,
- parameter REG_ENABLE = 1,
- parameter CLK_PERIOD = 3000,
- parameter DDR_TYPE = 1,
- parameter SIM_ONLY = 0,
- parameter DEBUG_EN = 0,
- parameter FPGA_SPEED_GRADE = 2
- )
- (
- input clk0,
- input clk90,
- input clkdiv0,
- input rst0,
- input rst90,
- input rstdiv0,
- input dm_ce,
- input [1:0] dq_oe_n,
- input dqs_oe_n,
- input dqs_rst_n,
- input [3:0] calib_start,
- input ctrl_rden,
- input phy_init_rden,
- input calib_ref_done,
- output [3:0] calib_done,
- output calib_ref_req,
- output [DQS_WIDTH-1:0] calib_rden,
- output [DQS_WIDTH-1:0] calib_rden_sel,
- input [DQ_WIDTH-1:0] wr_data_rise,
- input [DQ_WIDTH-1:0] wr_data_fall,
- input [(DQ_WIDTH/8)-1:0] mask_data_rise,
- input [(DQ_WIDTH/8)-1:0] mask_data_fall,
- output [(DQ_WIDTH)-1:0] rd_data_rise,
- output [(DQ_WIDTH)-1:0] rd_data_fall,
- output [CLK_WIDTH-1:0] ddr_ck,
- output [CLK_WIDTH-1:0] ddr_ck_n,
- output [DM_WIDTH-1:0] ddr_dm,
- inout [DQS_WIDTH-1:0] ddr_dqs,
- inout [DQS_WIDTH-1:0] ddr_dqs_n,
- inout [DQ_WIDTH-1:0] ddr_dq,
- // Debug signals (optional use)
- input dbg_idel_up_all,
- input dbg_idel_down_all,
- input dbg_idel_up_dq,
- input dbg_idel_down_dq,
- input dbg_idel_up_dqs,
- input dbg_idel_down_dqs,
- input dbg_idel_up_gate,
- input dbg_idel_down_gate,
- input [DQ_BITS-1:0] dbg_sel_idel_dq,
- input dbg_sel_all_idel_dq,
- input [DQS_BITS:0] dbg_sel_idel_dqs,
- input dbg_sel_all_idel_dqs,
- input [DQS_BITS:0] dbg_sel_idel_gate,
- input dbg_sel_all_idel_gate,
- output [3:0] dbg_calib_done,
- output [3:0] dbg_calib_err,
- output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
- output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
- );
-
- // ratio of # of physical DM outputs to bytes in data bus
- // may be different - e.g. if using x4 components
- localparam DM_TO_BYTE_RATIO = DM_WIDTH / (DQ_WIDTH/8);
-
- wire [CLK_WIDTH-1:0] ddr_ck_q;
- wire [DQS_WIDTH-1:0] delayed_dqs;
- wire [DQ_WIDTH-1:0] dlyce_dq;
- wire [DQS_WIDTH-1:0] dlyce_dqs;
- wire [DQS_WIDTH-1:0] dlyce_gate;
- wire [DQ_WIDTH-1:0] dlyinc_dq;
- wire [DQS_WIDTH-1:0] dlyinc_dqs;
- wire [DQS_WIDTH-1:0] dlyinc_gate;
- wire dlyrst_dq;
- wire dlyrst_dqs;
- wire [DQS_WIDTH-1:0] dlyrst_gate;
- wire [DQS_WIDTH-1:0] dq_ce;
- (* KEEP = "TRUE" *) wire [DQS_WIDTH-1:0] en_dqs /* synthesis syn_keep = 1 */;
- wire [DQS_WIDTH-1:0] rd_data_sel;
-
- //***************************************************************************
-
- ddr2_phy_calib #
- (
- .DQ_WIDTH (DQ_WIDTH),
- .DQ_BITS (DQ_BITS),
- .DQ_PER_DQS (DQ_PER_DQS),
- .DQS_BITS (DQS_BITS),
- .DQS_WIDTH (DQS_WIDTH),
- .ADDITIVE_LAT (ADDITIVE_LAT),
- .CAS_LAT (CAS_LAT),
- .REG_ENABLE (REG_ENABLE),
- .CLK_PERIOD (CLK_PERIOD),
- .SIM_ONLY (SIM_ONLY),
- .DEBUG_EN (DEBUG_EN)
- )
- u_phy_calib
- (
- .clk (clk0),
- .clkdiv (clkdiv0),
- .rstdiv (rstdiv0),
- .calib_start (calib_start),
- .ctrl_rden (ctrl_rden),
- .phy_init_rden (phy_init_rden),
- .rd_data_rise (rd_data_rise),
- .rd_data_fall (rd_data_fall),
- .calib_ref_done (calib_ref_done),
- .calib_done (calib_done),
- .calib_ref_req (calib_ref_req),
- .calib_rden (calib_rden),
- .calib_rden_sel (calib_rden_sel),
- .dlyrst_dq (dlyrst_dq),
- .dlyce_dq (dlyce_dq),
- .dlyinc_dq (dlyinc_dq),
- .dlyrst_dqs (dlyrst_dqs),
- .dlyce_dqs (dlyce_dqs),
- .dlyinc_dqs (dlyinc_dqs),
- .dlyrst_gate (dlyrst_gate),
- .dlyce_gate (dlyce_gate),
- .dlyinc_gate (dlyinc_gate),
- .en_dqs (en_dqs),
- .rd_data_sel (rd_data_sel),
- .dbg_idel_up_all (dbg_idel_up_all),
- .dbg_idel_down_all (dbg_idel_down_all),
- .dbg_idel_up_dq (dbg_idel_up_dq),
- .dbg_idel_down_dq (dbg_idel_down_dq),
- .dbg_idel_up_dqs (dbg_idel_up_dqs),
- .dbg_idel_down_dqs (dbg_idel_down_dqs),
- .dbg_idel_up_gate (dbg_idel_up_gate),
- .dbg_idel_down_gate (dbg_idel_down_gate),
- .dbg_sel_idel_dq (dbg_sel_idel_dq),
- .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
- .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
- .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
- .dbg_sel_idel_gate (dbg_sel_idel_gate),
- .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
- .dbg_calib_done (dbg_calib_done),
- .dbg_calib_err (dbg_calib_err),
- .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
- .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
- .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
- .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
- .dbg_calib_rden_dly (dbg_calib_rden_dly),
- .dbg_calib_gate_dly (dbg_calib_gate_dly)
- );
-
- //***************************************************************************
- // Memory clock generation
- //***************************************************************************
-
- genvar ck_i;
- generate
- for(ck_i = 0; ck_i < CLK_WIDTH; ck_i = ck_i+1) begin: gen_ck
- ODDR #
- (
- .SRTYPE ("SYNC"),
- .DDR_CLK_EDGE ("OPPOSITE_EDGE")
- )
- u_oddr_ck_i
- (
- .Q (ddr_ck_q[ck_i]),
- .C (clk0),
- .CE (1'b1),
- .D1 (1'b0),
- .D2 (1'b1),
- .R (1'b0),
- .S (1'b0)
- );
- // Can insert ODELAY here if required
- OBUFDS u_obuf_ck_i
- (
- .I (ddr_ck_q[ck_i]),
- .O (ddr_ck[ck_i]),
- .OB (ddr_ck_n[ck_i])
- );
- end
- endgenerate
-
- //***************************************************************************
- // DQS instances
- //***************************************************************************
-
- genvar dqs_i;
- generate
- for(dqs_i = 0; dqs_i < DQS_WIDTH; dqs_i = dqs_i+1) begin: gen_dqs
- ddr2_phy_dqs_iob #
- (
- .DDR_TYPE (DDR_TYPE),
- .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
- .IODELAY_GRP (IODELAY_GRP)
- )
- u_iob_dqs
- (
- .clk0 (clk0),
- .clkdiv0 (clkdiv0),
- .rst0 (rst0),
- .dlyinc_dqs (dlyinc_dqs[dqs_i]),
- .dlyce_dqs (dlyce_dqs[dqs_i]),
- .dlyrst_dqs (dlyrst_dqs),
- .dlyinc_gate (dlyinc_gate[dqs_i]),
- .dlyce_gate (dlyce_gate[dqs_i]),
- .dlyrst_gate (dlyrst_gate[dqs_i]),
- .dqs_oe_n (dqs_oe_n),
- .dqs_rst_n (dqs_rst_n),
- .en_dqs (en_dqs[dqs_i]),
- .ddr_dqs (ddr_dqs[dqs_i]),
- .ddr_dqs_n (ddr_dqs_n[dqs_i]),
- .dq_ce (dq_ce[dqs_i]),
- .delayed_dqs (delayed_dqs[dqs_i])
- );
- end
- endgenerate
-
- //***************************************************************************
- // DM instances
- //***************************************************************************
-
- genvar dm_i;
- generate
- if (USE_DM_PORT) begin: gen_dm_inst
- for(dm_i = 0; dm_i < DM_WIDTH; dm_i = dm_i+1) begin: gen_dm
- ddr2_phy_dm_iob u_iob_dm
- (
- .clk90 (clk90),
- .dm_ce (dm_ce),
- .mask_data_rise (mask_data_rise[dm_i/DM_TO_BYTE_RATIO]),
- .mask_data_fall (mask_data_fall[dm_i/DM_TO_BYTE_RATIO]),
- .ddr_dm (ddr_dm[dm_i])
- );
- end
- end
- endgenerate
-
- //***************************************************************************
- // DQ IOB instances
- //***************************************************************************
-
- genvar dq_i;
- generate
- for(dq_i = 0; dq_i < DQ_WIDTH; dq_i = dq_i+1) begin: gen_dq
- ddr2_phy_dq_iob #
- (
- .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
- .IODELAY_GRP (IODELAY_GRP),
- .FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
- )
- u_iob_dq
- (
- .clk0 (clk0),
- .clk90 (clk90),
- .clkdiv0 (clkdiv0),
- .rst90 (rst90),
- .dlyinc (dlyinc_dq[dq_i]),
- .dlyce (dlyce_dq[dq_i]),
- .dlyrst (dlyrst_dq),
- .dq_oe_n (dq_oe_n),
- .dqs (delayed_dqs[dq_i/DQ_PER_DQS]),
- .ce (dq_ce[dq_i/DQ_PER_DQS]),
- .rd_data_sel (rd_data_sel[dq_i/DQ_PER_DQS]),
- .wr_data_rise (wr_data_rise[dq_i]),
- .wr_data_fall (wr_data_fall[dq_i]),
- .rd_data_rise (rd_data_rise[dq_i]),
- .rd_data_fall (rd_data_fall[dq_i]),
- .ddr_dq (ddr_dq[dq_i])
- );
- end
- endgenerate
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/MEMCtrl.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/MEMCtrl.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/MEMCtrl.v (nonexistent)
@@ -1,605 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: MEMCtrl.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// Top-level module. Simple model for what the user might use
-// Typically, the user will only instantiate MEM_INTERFACE_TOP in their
-// code, and generate all backend logic (test bench) and all the other infrastructure logic
-// separately.
-// In addition to the memory controller, the module instantiates:
-// 1. Reset logic based on user clocks
-// 2. IDELAY control block
-//Reference:
-//Revision History:
-// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
-// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
-// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-(* X_CORE_INFO = "mig_v3_61_ddr2_v5, Coregen 12.4" , CORE_GENERATION_INFO = "ddr2_v5,mig_v3_61,{component_name=MEMCtrl, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=3, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, CLK_PERIOD=8000, RST_ACT_LOW=1, INTERFACE_TYPE=DDR2_SDRAM, LANGUAGE=Verilog, SYNTHESIS_TOOL=ISE, NO_OF_CONTROLLERS=1}" *)
-module MEMCtrl #
- (
- parameter BANK_WIDTH = 2,
- // # of memory bank addr bits.
- parameter CKE_WIDTH = 1,
- // # of memory clock enable outputs.
- parameter CLK_WIDTH = 2,
- // # of clock outputs.
- parameter COL_WIDTH = 10,
- // # of memory column bits.
- parameter CS_NUM = 1,
- // # of separate memory chip selects.
- parameter CS_WIDTH = 1,
- // # of total memory chip selects.
- parameter CS_BITS = 0,
- // set to log2(CS_NUM) (rounded up).
- parameter DM_WIDTH = 8,
- // # of data mask bits.
- parameter DQ_WIDTH = 64,
- // # of data width.
- parameter DQ_PER_DQS = 8,
- // # of DQ data bits per strobe.
- parameter DQS_WIDTH = 8,
- // # of DQS strobes.
- parameter DQ_BITS = 6,
- // set to log2(DQS_WIDTH*DQ_PER_DQS).
- parameter DQS_BITS = 3,
- // set to log2(DQS_WIDTH).
- parameter ODT_WIDTH = 1,
- // # of memory on-die term enables.
- parameter ROW_WIDTH = 13,
- // # of memory row and # of addr bits.
- parameter ADDITIVE_LAT = 0,
- // additive write latency.
- parameter BURST_LEN = 4,
- // burst length (in double words).
- parameter BURST_TYPE = 0,
- // burst type (=0 seq; =1 interleaved).
- parameter CAS_LAT = 3,
- // CAS latency.
- parameter ECC_ENABLE = 0,
- // enable ECC (=1 enable).
- parameter APPDATA_WIDTH = 128,
- // # of usr read/write data bus bits.
- parameter MULTI_BANK_EN = 1,
- // Keeps multiple banks open. (= 1 enable).
- parameter TWO_T_TIME_EN = 1,
- // 2t timing for unbuffered dimms.
- parameter ODT_TYPE = 1,
- // ODT (=0(none),=1(75),=2(150),=3(50)).
- parameter REDUCE_DRV = 0,
- // reduced strength mem I/O (=1 yes).
- parameter REG_ENABLE = 0,
- // registered addr/ctrl (=1 yes).
- parameter TREFI_NS = 7800,
- // auto refresh interval (ns).
- parameter TRAS = 40000,
- // active->precharge delay.
- parameter TRCD = 15000,
- // active->read/write delay.
- parameter TRFC = 105000,
- // refresh->refresh, refresh->active delay.
- parameter TRP = 15000,
- // precharge->command delay.
- parameter TRTP = 7500,
- // read->precharge delay.
- parameter TWR = 15000,
- // used to determine write->precharge.
- parameter TWTR = 7500,
- // write->read delay.
- parameter HIGH_PERFORMANCE_MODE = "TRUE",
- // # = TRUE, the IODELAY performance mode is set
- // to high.
- // # = FALSE, the IODELAY performance mode is set
- // to low.
- parameter SIM_ONLY = 0,
- // = 1 to skip SDRAM power up delay.
- parameter DEBUG_EN = 0,
- // Enable debug signals/controls.
- // When this parameter is changed from 0 to 1,
- // make sure to uncomment the coregen commands
- // in ise_flow.bat or create_ise.bat files in
- // par folder.
- parameter CLK_PERIOD = 8000,
- // Core/Memory clock period (in ps).
- parameter RST_ACT_LOW = 1
- // =1 for active low reset, =0 for active high.
- )
- (
- inout [DQ_WIDTH-1:0] ddr2_dq,
- output [ROW_WIDTH-1:0] ddr2_a,
- output [BANK_WIDTH-1:0] ddr2_ba,
- output ddr2_ras_n,
- output ddr2_cas_n,
- output ddr2_we_n,
- output [CS_WIDTH-1:0] ddr2_cs_n,
- output [ODT_WIDTH-1:0] ddr2_odt,
- output [CKE_WIDTH-1:0] ddr2_cke,
- output [DM_WIDTH-1:0] ddr2_dm,
- input sys_rst_n,
- output phy_init_done,
- input locked,
- output rst0_tb,
- input clk0,
- output clk0_tb,
- input clk90,
- input clkdiv0,
- input clk200,
- output app_wdf_afull,
- output app_af_afull,
- output rd_data_valid,
- input app_wdf_wren,
- input app_af_wren,
- input [30:0] app_af_addr,
- input [2:0] app_af_cmd,
- output [(APPDATA_WIDTH)-1:0] rd_data_fifo_out,
- input [(APPDATA_WIDTH)-1:0] app_wdf_data,
- input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
- inout [DQS_WIDTH-1:0] ddr2_dqs,
- inout [DQS_WIDTH-1:0] ddr2_dqs_n,
- output [CLK_WIDTH-1:0] ddr2_ck,
- output [CLK_WIDTH-1:0] ddr2_ck_n//,
- //ADAUGAT PT LEDURI
- //output error_o, error_cmp_o
- );
-
- //***************************************************************************
- // IODELAY Group Name: Replication and placement of IDELAYCTRLs will be
- // handled automatically by software tools if IDELAYCTRLs have same refclk,
- // reset and rdy nets. Designs with a unique RESET will commonly create a
- // unique RDY. Constraint IODELAY_GROUP is associated to a set of IODELAYs
- // with an IDELAYCTRL. The parameter IODELAY_GRP value can be any string.
- //***************************************************************************
-
- localparam IODELAY_GRP = "IODELAY_MIG";
-
-
-
-
-
- wire rst0;
- wire rst90;
- wire rstdiv0;
- wire rst200;
- wire idelay_ctrl_rdy;
-
- wire error;
- wire error_cmp;
- wire [35:0] control;
- wire [71:0] data;
- wire [7:0] trig0;
-
- //Debug signals
-
-
- wire [3:0] dbg_calib_done;
- wire [3:0] dbg_calib_err;
- wire [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt;
- wire [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt;
- wire [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt;
- wire [DQS_WIDTH-1:0] dbg_calib_rd_data_sel;
- wire [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly;
- wire [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly;
- wire dbg_idel_up_all;
- wire dbg_idel_down_all;
- wire dbg_idel_up_dq;
- wire dbg_idel_down_dq;
- wire dbg_idel_up_dqs;
- wire dbg_idel_down_dqs;
- wire dbg_idel_up_gate;
- wire dbg_idel_down_gate;
- wire [DQ_BITS-1:0] dbg_sel_idel_dq;
- wire dbg_sel_all_idel_dq;
- wire [DQS_BITS:0] dbg_sel_idel_dqs;
- wire dbg_sel_all_idel_dqs;
- wire [DQS_BITS:0] dbg_sel_idel_gate;
- wire dbg_sel_all_idel_gate;
-
-
- // Debug signals (optional use)
-
- //***********************************
- // PHY Debug Port demo
- //***********************************
- wire [35:0] cs_control0;
- wire [35:0] cs_control1;
- wire [35:0] cs_control2;
- wire [35:0] cs_control3;
- wire [191:0] vio0_in;
- wire [95:0] vio1_in;
- wire [99:0] vio2_in;
- wire [31:0] vio3_out;
-
-
-
-
- //***************************************************************************
-
- assign rst0_tb = rst0;
- assign clk0_tb = clk0;
-
-
-ddr2_idelay_ctrl #
- (
- .IODELAY_GRP (IODELAY_GRP)
- )
- u_ddr2_idelay_ctrl
- (
- .rst200 (rst200),
- .clk200 (clk200),
- .idelay_ctrl_rdy (idelay_ctrl_rdy)
- );
-
- ddr2_infrastructure #
- (
- .RST_ACT_LOW (RST_ACT_LOW)
- )
-u_ddr2_infrastructure
- (
- .sys_rst_n (sys_rst_n),
- .locked (locked),
- .rst0 (rst0),
- .rst90 (rst90),
- .rstdiv0 (rstdiv0),
- .rst200 (rst200),
- .clk0 (clk0),
- .clk90 (clk90),
- .clkdiv0 (clkdiv0),
- .clk200 (clk200),
- .idelay_ctrl_rdy (idelay_ctrl_rdy)
- );
-
- ddr2_top #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .CKE_WIDTH (CKE_WIDTH),
- .CLK_WIDTH (CLK_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .CS_NUM (CS_NUM),
- .CS_WIDTH (CS_WIDTH),
- .CS_BITS (CS_BITS),
- .DM_WIDTH (DM_WIDTH),
- .DQ_WIDTH (DQ_WIDTH),
- .DQ_PER_DQS (DQ_PER_DQS),
- .DQS_WIDTH (DQS_WIDTH),
- .DQ_BITS (DQ_BITS),
- .DQS_BITS (DQS_BITS),
- .ODT_WIDTH (ODT_WIDTH),
- .ROW_WIDTH (ROW_WIDTH),
- .ADDITIVE_LAT (ADDITIVE_LAT),
- .BURST_LEN (BURST_LEN),
- .BURST_TYPE (BURST_TYPE),
- .CAS_LAT (CAS_LAT),
- .ECC_ENABLE (ECC_ENABLE),
- .APPDATA_WIDTH (APPDATA_WIDTH),
- .MULTI_BANK_EN (MULTI_BANK_EN),
- .TWO_T_TIME_EN (TWO_T_TIME_EN),
- .ODT_TYPE (ODT_TYPE),
- .REDUCE_DRV (REDUCE_DRV),
- .REG_ENABLE (REG_ENABLE),
- .TREFI_NS (TREFI_NS),
- .TRAS (TRAS),
- .TRCD (TRCD),
- .TRFC (TRFC),
- .TRP (TRP),
- .TRTP (TRTP),
- .TWR (TWR),
- .TWTR (TWTR),
- .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
- .IODELAY_GRP (IODELAY_GRP),
- .SIM_ONLY (SIM_ONLY),
- .DEBUG_EN (DEBUG_EN),
- .FPGA_SPEED_GRADE (3),
- .USE_DM_PORT (1),
- .CLK_PERIOD (CLK_PERIOD)
- )
-u_ddr2_top_0
-(
- .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),
- .phy_init_done (phy_init_done),
- .rst0 (rst0),
- .rst90 (rst90),
- .rstdiv0 (rstdiv0),
- .clk0 (clk0),
- .clk90 (clk90),
- .clkdiv0 (clkdiv0),
- .app_wdf_afull (app_wdf_afull),
- .app_af_afull (app_af_afull),
- .rd_data_valid (rd_data_valid),
- .app_wdf_wren (app_wdf_wren),
- .app_af_wren (app_af_wren),
- .app_af_addr (app_af_addr),
- .app_af_cmd (app_af_cmd),
- .rd_data_fifo_out (rd_data_fifo_out),
- .app_wdf_data (app_wdf_data),
- .app_wdf_mask_data (app_wdf_mask_data),
- .ddr2_dqs (ddr2_dqs),
- .ddr2_dqs_n (ddr2_dqs_n),
- .ddr2_ck (ddr2_ck),
- .rd_ecc_error (),
- .ddr2_ck_n (ddr2_ck_n),
-
- .dbg_calib_done (dbg_calib_done),
- .dbg_calib_err (dbg_calib_err),
- .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
- .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
- .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
- .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
- .dbg_calib_rden_dly (dbg_calib_rden_dly),
- .dbg_calib_gate_dly (dbg_calib_gate_dly),
- .dbg_idel_up_all (dbg_idel_up_all),
- .dbg_idel_down_all (dbg_idel_down_all),
- .dbg_idel_up_dq (dbg_idel_up_dq),
- .dbg_idel_down_dq (dbg_idel_down_dq),
- .dbg_idel_up_dqs (dbg_idel_up_dqs),
- .dbg_idel_down_dqs (dbg_idel_down_dqs),
- .dbg_idel_up_gate (dbg_idel_up_gate),
- .dbg_idel_down_gate (dbg_idel_down_gate),
- .dbg_sel_idel_dq (dbg_sel_idel_dq),
- .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
- .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
- .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
- .dbg_sel_idel_gate (dbg_sel_idel_gate),
- .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate)
- );
-
-
- //*****************************************************************
- // Hooks to prevent sim/syn compilation errors (mainly for VHDL - but
- // keep it also in Verilog version of code) w/ floating inputs if
- // DEBUG_EN = 0.
- //*****************************************************************
-
- generate
- if (DEBUG_EN == 0) begin: gen_dbg_tie_off
- assign dbg_idel_up_all = 'b0;
- assign dbg_idel_down_all = 'b0;
- assign dbg_idel_up_dq = 'b0;
- assign dbg_idel_down_dq = 'b0;
- assign dbg_idel_up_dqs = 'b0;
- assign dbg_idel_down_dqs = 'b0;
- assign dbg_idel_up_gate = 'b0;
- assign dbg_idel_down_gate = 'b0;
- assign dbg_sel_idel_dq = 'b0;
- assign dbg_sel_all_idel_dq = 'b0;
- assign dbg_sel_idel_dqs = 'b0;
- assign dbg_sel_all_idel_dqs = 'b0;
- assign dbg_sel_idel_gate = 'b0;
- assign dbg_sel_all_idel_gate = 'b0;
- end else begin: gen_dbg_enable
-
- //*****************************************************************
- // PHY Debug Port example - see MIG User's Guide, XAPP858 or
- // Answer Record 29443
- // This logic supports up to 32 DQ and 8 DQS I/O
- // NOTES:
- // 1. PHY Debug Port demo connects to 4 VIO modules:
- // - 3 VIO modules with only asynchronous inputs
- // * Monitor IDELAY taps for DQ, DQS, DQS Gate
- // * Calibration status
- // - 1 VIO module with synchronous outputs
- // * Allow dynamic adjustment o f IDELAY taps
- // 2. User may need to modify this code to incorporate other
- // chipscope-related modules in their larger design (e.g.
- // if they have other ILA/VIO modules, they will need to
- // for example instantiate a larger ICON module). In addition
- // user may want to instantiate more VIO modules to control
- // IDELAY for more DQ, DQS than is shown here
- //*****************************************************************
-
- icon4 u_icon
- (
- .control0 (cs_control0),
- .control1 (cs_control1),
- .control2 (cs_control2),
- .control3 (cs_control3)
- );
-
- //*****************************************************************
- // VIO ASYNC input: Display current IDELAY setting for up to 32
- // DQ taps (32x6) = 192
- //*****************************************************************
-
- vio_async_in192 u_vio0
- (
- .control (cs_control0),
- .async_in (vio0_in)
- );
-
- //*****************************************************************
- // VIO ASYNC input: Display current IDELAY setting for up to 8 DQS
- // and DQS Gate taps (8x6x2) = 96
- //*****************************************************************
-
- vio_async_in96 u_vio1
- (
- .control (cs_control1),
- .async_in (vio1_in)
- );
-
- //*****************************************************************
- // VIO ASYNC input: Display other calibration results
- //*****************************************************************
-
- vio_async_in100 u_vio2
- (
- .control (cs_control2),
- .async_in (vio2_in)
- );
-
- //*****************************************************************
- // VIO SYNC output: Dynamically change IDELAY taps
- //*****************************************************************
-
- vio_sync_out32 u_vio3
- (
- .control (cs_control3),
- .clk (clkdiv0),
- .sync_out (vio3_out)
- );
-
- //*****************************************************************
- // Bit assignments:
- // NOTE: Not all VIO, ILA inputs/outputs may be used - these will
- // be dependent on the user's particular bit width
- //*****************************************************************
-
- if (DQ_WIDTH <= 32) begin: gen_dq_le_32
- assign vio0_in[(6*DQ_WIDTH)-1:0]
- = dbg_calib_dq_tap_cnt[(6*DQ_WIDTH)-1:0];
- end else begin: gen_dq_gt_32
- assign vio0_in = dbg_calib_dq_tap_cnt[191:0];
- end
-
- if (DQS_WIDTH <= 8) begin: gen_dqs_le_8
- assign vio1_in[(6*DQS_WIDTH)-1:0]
- = dbg_calib_dqs_tap_cnt[(6*DQS_WIDTH)-1:0];
- assign vio1_in[(12*DQS_WIDTH)-1:(6*DQS_WIDTH)]
- = dbg_calib_gate_tap_cnt[(6*DQS_WIDTH)-1:0];
- end else begin: gen_dqs_gt_32
- assign vio1_in[47:0] = dbg_calib_dqs_tap_cnt[47:0];
- assign vio1_in[95:48] = dbg_calib_gate_tap_cnt[47:0];
- end
-
-//dbg_calib_rd_data_sel
-
- if (DQS_WIDTH <= 8) begin: gen_rdsel_le_8
- assign vio2_in[(DQS_WIDTH)+7:8]
- = dbg_calib_rd_data_sel[(DQS_WIDTH)-1:0];
- end else begin: gen_rdsel_gt_32
- assign vio2_in[15:8]
- = dbg_calib_rd_data_sel[7:0];
- end
-
-//dbg_calib_rden_dly
-
- if (DQS_WIDTH <= 8) begin: gen_calrd_le_8
- assign vio2_in[(5*DQS_WIDTH)+19:20]
- = dbg_calib_rden_dly[(5*DQS_WIDTH)-1:0];
- end else begin: gen_calrd_gt_32
- assign vio2_in[59:20]
- = dbg_calib_rden_dly[39:0];
- end
-
-//dbg_calib_gate_dly
-
- if (DQS_WIDTH <= 8) begin: gen_calgt_le_8
- assign vio2_in[(5*DQS_WIDTH)+59:60]
- = dbg_calib_gate_dly[(5*DQS_WIDTH)-1:0];
- end else begin: gen_calgt_gt_32
- assign vio2_in[99:60]
- = dbg_calib_gate_dly[39:0];
- end
-
-//dbg_sel_idel_dq
-
- if (DQ_BITS <= 5) begin: gen_selid_le_5
- assign dbg_sel_idel_dq[DQ_BITS-1:0]
- = vio3_out[DQ_BITS+7:8];
- end else begin: gen_selid_gt_32
- assign dbg_sel_idel_dq[4:0]
- = vio3_out[12:8];
- end
-
-//dbg_sel_idel_dqs
-
- if (DQS_BITS <= 3) begin: gen_seldqs_le_3
- assign dbg_sel_idel_dqs[DQS_BITS:0]
- = vio3_out[(DQS_BITS+16):16];
- end else begin: gen_seldqs_gt_32
- assign dbg_sel_idel_dqs[3:0]
- = vio3_out[19:16];
- end
-
-//dbg_sel_idel_gate
-
- if (DQS_BITS <= 3) begin: gen_gtdqs_le_3
- assign dbg_sel_idel_gate[DQS_BITS:0]
- = vio3_out[(DQS_BITS+21):21];
- end else begin: gen_gtdqs_gt_32
- assign dbg_sel_idel_gate[3:0]
- = vio3_out[24:21];
- end
-
-
- assign vio2_in[3:0] = dbg_calib_done;
- assign vio2_in[7:4] = dbg_calib_err;
-
- assign dbg_idel_up_all = vio3_out[0];
- assign dbg_idel_down_all = vio3_out[1];
- assign dbg_idel_up_dq = vio3_out[2];
- assign dbg_idel_down_dq = vio3_out[3];
- assign dbg_idel_up_dqs = vio3_out[4];
- assign dbg_idel_down_dqs = vio3_out[5];
- assign dbg_idel_up_gate = vio3_out[6];
- assign dbg_idel_down_gate = vio3_out[7];
- assign dbg_sel_all_idel_dq = vio3_out[15];
- assign dbg_sel_all_idel_dqs = vio3_out[20];
- assign dbg_sel_all_idel_gate = vio3_out[25];
- end
- endgenerate
-
-
-endmodule
-
-
-
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_ctl_io.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_ctl_io.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_ctl_io.v (nonexistent)
@@ -1,304 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_phy_ctl_io.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Thu Aug 24 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module puts the memory control signals like address, bank address,
-// row address strobe, column address strobe, write enable and clock enable
-// in the IOBs.
-//Reference:
-//Revision History:
-// Rev 1.1 - To fix CR 540201, S attribute is added for CS, CKE and ODT
-// module (FDCPE) instances. PK. 01/08/10
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_phy_ctl_io #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter CKE_WIDTH = 1,
- parameter COL_WIDTH = 10,
- parameter CS_NUM = 1,
- parameter TWO_T_TIME_EN = 0,
- parameter CS_WIDTH = 1,
- parameter ODT_WIDTH = 1,
- parameter ROW_WIDTH = 14,
- parameter DDR_TYPE = 1
- )
- (
- input clk0,
- input clk90,
- input rst0,
- input rst90,
- input [ROW_WIDTH-1:0] ctrl_addr,
- input [BANK_WIDTH-1:0] ctrl_ba,
- input ctrl_ras_n,
- input ctrl_cas_n,
- input ctrl_we_n,
- input [CS_NUM-1:0] ctrl_cs_n,
- input [ROW_WIDTH-1:0] phy_init_addr,
- input [BANK_WIDTH-1:0] phy_init_ba,
- input phy_init_ras_n,
- input phy_init_cas_n,
- input phy_init_we_n,
- input [CS_NUM-1:0] phy_init_cs_n,
- input [CKE_WIDTH-1:0] phy_init_cke,
- input phy_init_data_sel,
- input [CS_NUM-1:0] odt,
- output [ROW_WIDTH-1:0] ddr_addr,
- output [BANK_WIDTH-1:0] ddr_ba,
- output ddr_ras_n,
- output ddr_cas_n,
- output ddr_we_n,
- output [CKE_WIDTH-1:0] ddr_cke,
- output [CS_WIDTH-1:0] ddr_cs_n,
- output [ODT_WIDTH-1:0] ddr_odt
- );
-
- reg [ROW_WIDTH-1:0] addr_mux;
- reg [BANK_WIDTH-1:0] ba_mux;
- reg cas_n_mux;
- reg [CS_NUM-1:0] cs_n_mux;
- reg ras_n_mux;
- reg we_n_mux;
-
-
-
- //***************************************************************************
-
-
-
-
- // MUX to choose from either PHY or controller for SDRAM control
-
- generate // in 2t timing mode the extra register stage cannot be used.
- if(TWO_T_TIME_EN) begin // the control signals are asserted for two cycles
- always @(*)begin
- if (phy_init_data_sel) begin
- addr_mux = ctrl_addr;
- ba_mux = ctrl_ba;
- cas_n_mux = ctrl_cas_n;
- cs_n_mux = ctrl_cs_n;
- ras_n_mux = ctrl_ras_n;
- we_n_mux = ctrl_we_n;
- end else begin
- addr_mux = phy_init_addr;
- ba_mux = phy_init_ba;
- cas_n_mux = phy_init_cas_n;
- cs_n_mux = phy_init_cs_n;
- ras_n_mux = phy_init_ras_n;
- we_n_mux = phy_init_we_n;
- end
- end
- end else begin
- always @(posedge clk0)begin // register the signals in non 2t mode
- if (phy_init_data_sel) begin
- addr_mux <= ctrl_addr;
- ba_mux <= ctrl_ba;
- cas_n_mux <= ctrl_cas_n;
- cs_n_mux <= ctrl_cs_n;
- ras_n_mux <= ctrl_ras_n;
- we_n_mux <= ctrl_we_n;
- end else begin
- addr_mux <= phy_init_addr;
- ba_mux <= phy_init_ba;
- cas_n_mux <= phy_init_cas_n;
- cs_n_mux <= phy_init_cs_n;
- ras_n_mux <= phy_init_ras_n;
- we_n_mux <= phy_init_we_n;
- end
- end
- end
- endgenerate
-
- //***************************************************************************
- // Output flop instantiation
- // NOTE: Make sure all control/address flops are placed in IOBs
- //***************************************************************************
-
- // RAS: = 1 at reset
- (* IOB = "FORCE" *) FDCPE u_ff_ras_n
- (
- .Q (ddr_ras_n),
- .C (clk0),
- .CE (1'b1),
- .CLR (1'b0),
- .D (ras_n_mux),
- .PRE (rst0)
- ) /* synthesis syn_useioff = 1 */;
-
- // CAS: = 1 at reset
- (* IOB = "FORCE" *) FDCPE u_ff_cas_n
- (
- .Q (ddr_cas_n),
- .C (clk0),
- .CE (1'b1),
- .CLR (1'b0),
- .D (cas_n_mux),
- .PRE (rst0)
- ) /* synthesis syn_useioff = 1 */;
-
- // WE: = 1 at reset
- (* IOB = "FORCE" *) FDCPE u_ff_we_n
- (
- .Q (ddr_we_n),
- .C (clk0),
- .CE (1'b1),
- .CLR (1'b0),
- .D (we_n_mux),
- .PRE (rst0)
- ) /* synthesis syn_useioff = 1 */;
-
- // CKE: = 0 at reset
- genvar cke_i;
- generate
- for (cke_i = 0; cke_i < CKE_WIDTH; cke_i = cke_i + 1) begin: gen_cke
- (* IOB = "FORCE" *) (* S = "TRUE" *) FDCPE u_ff_cke
- (
- .Q (ddr_cke[cke_i]),
- .C (clk0),
- .CE (1'b1),
- .CLR (rst0),
- .D (phy_init_cke[cke_i]),
- .PRE (1'b0)
- ) /* synthesis syn_useioff = 1 */;
- end
- endgenerate
-
- // chip select: = 1 at reset
- // For unbuffered dimms the loading will be high. The chip select
- // can be asserted early if the loading is very high. The
- // code as is uses clock 0. If needed clock 270 can be used to
- // toggle chip select 1/4 clock cycle early. The code has
- // the clock 90 input for the early assertion of chip select.
-
- genvar cs_i;
- generate
- for(cs_i = 0; cs_i < CS_WIDTH; cs_i = cs_i + 1) begin: gen_cs_n
- if(TWO_T_TIME_EN) begin
- (* IOB = "FORCE" *) (* S = "TRUE" *) FDCPE u_ff_cs_n
- (
- .Q (ddr_cs_n[cs_i]),
- .C (clk0),
- .CE (1'b1),
- .CLR (1'b0),
- .D (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
- .PRE (rst0)
- ) /* synthesis syn_useioff = 1 */;
- end else begin // if (TWO_T_TIME_EN)
- (* IOB = "FORCE" *) (* S = "TRUE" *) FDCPE u_ff_cs_n
- (
- .Q (ddr_cs_n[cs_i]),
- .C (clk0),
- .CE (1'b1),
- .CLR (1'b0),
- .D (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
- .PRE (rst0)
- ) /* synthesis syn_useioff = 1 */;
- end // else: !if(TWO_T_TIME_EN)
- end
- endgenerate
-
- // address: = X at reset
- genvar addr_i;
- generate
- for (addr_i = 0; addr_i < ROW_WIDTH; addr_i = addr_i + 1) begin: gen_addr
- (* IOB = "FORCE" *) FDCPE u_ff_addr
- (
- .Q (ddr_addr[addr_i]),
- .C (clk0),
- .CE (1'b1),
- .CLR (1'b0),
- .D (addr_mux[addr_i]),
- .PRE (1'b0)
- ) /* synthesis syn_useioff = 1 */;
- end
- endgenerate
-
- // bank address = X at reset
- genvar ba_i;
- generate
- for (ba_i = 0; ba_i < BANK_WIDTH; ba_i = ba_i + 1) begin: gen_ba
- (* IOB = "FORCE" *) FDCPE u_ff_ba
- (
- .Q (ddr_ba[ba_i]),
- .C (clk0),
- .CE (1'b1),
- .CLR (1'b0),
- .D (ba_mux[ba_i]),
- .PRE (1'b0)
- ) /* synthesis syn_useioff = 1 */;
- end
- endgenerate
-
- // ODT control = 0 at reset
- genvar odt_i;
- generate
- if (DDR_TYPE > 0) begin: gen_odt_ddr2
- for (odt_i = 0; odt_i < ODT_WIDTH; odt_i = odt_i + 1) begin: gen_odt
- (* IOB = "FORCE" *) (* S = "TRUE" *) FDCPE u_ff_odt
- (
- .Q (ddr_odt[odt_i]),
- .C (clk0),
- .CE (1'b1),
- .CLR (rst0),
- .D (odt[(odt_i*CS_NUM)/ODT_WIDTH]),
- .PRE (1'b0)
- ) /* synthesis syn_useioff = 1 */;
- end
- end
- endgenerate
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_calib.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_calib.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_calib.v (nonexistent)
@@ -1,2428 +0,0 @@
-//*****************************************************************************
-// (c) Copyright 2006-2009 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.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_phy_calib.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Thu Aug 10 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module handles calibration after memory initialization.
-//Reference:
-//Revision History:
-// Rev 1.1 - Default statement is added for the CASE statement of
-// rdd_mux_sel logic. PK. 03/23/09
-// Rev 1.2 - Change training pattern detected for stage 3 calibration.
-// Use 2-bits per DQS group for stage 3 pattern detection.
-// RC. 09/21/09
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_phy_calib #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter DQ_WIDTH = 72,
- parameter DQ_BITS = 7,
- parameter DQ_PER_DQS = 8,
- parameter DQS_BITS = 4,
- parameter DQS_WIDTH = 9,
- parameter ADDITIVE_LAT = 0,
- parameter CAS_LAT = 5,
- parameter REG_ENABLE = 1,
- parameter CLK_PERIOD = 3000,
- parameter SIM_ONLY = 0,
- parameter DEBUG_EN = 0
- )
- (
- input clk,
- input clkdiv,
- input rstdiv,
- input [3:0] calib_start,
- input ctrl_rden,
- input phy_init_rden,
- input [DQ_WIDTH-1:0] rd_data_rise,
- input [DQ_WIDTH-1:0] rd_data_fall,
- input calib_ref_done,
- output reg [3:0] calib_done,
- output reg calib_ref_req,
- output [DQS_WIDTH-1:0] calib_rden,
- output reg [DQS_WIDTH-1:0] calib_rden_sel,
- output reg dlyrst_dq,
- output reg [DQ_WIDTH-1:0] dlyce_dq,
- output reg [DQ_WIDTH-1:0] dlyinc_dq,
- output reg dlyrst_dqs,
- output reg [DQS_WIDTH-1:0] dlyce_dqs,
- output reg [DQS_WIDTH-1:0] dlyinc_dqs,
- output reg [DQS_WIDTH-1:0] dlyrst_gate,
- output reg [DQS_WIDTH-1:0] dlyce_gate,
- output reg [DQS_WIDTH-1:0] dlyinc_gate,
- //(* XIL_PAR_NO_REG_ORDER = "TRUE", XIL_PAR_PATH="Q->u_iodelay_dq_ce.DATAIN", syn_keep = "1", keep = "TRUE"*)
- output [DQS_WIDTH-1:0] en_dqs,
- output [DQS_WIDTH-1:0] rd_data_sel,
- // Debug signals (optional use)
- input dbg_idel_up_all,
- input dbg_idel_down_all,
- input dbg_idel_up_dq,
- input dbg_idel_down_dq,
- input dbg_idel_up_dqs,
- input dbg_idel_down_dqs,
- input dbg_idel_up_gate,
- input dbg_idel_down_gate,
- input [DQ_BITS-1:0] dbg_sel_idel_dq,
- input dbg_sel_all_idel_dq,
- input [DQS_BITS:0] dbg_sel_idel_dqs,
- input dbg_sel_all_idel_dqs,
- input [DQS_BITS:0] dbg_sel_idel_gate,
- input dbg_sel_all_idel_gate,
- output [3:0] dbg_calib_done,
- output [3:0] dbg_calib_err,
- output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
- output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
- );
-
- // minimum time (in IDELAY taps) for which capture data must be stable for
- // algorithm to consider
- localparam MIN_WIN_SIZE = 5;
- // IDEL_SET_VAL = (# of cycles - 1) to wait after changing IDELAY value
- // we only have to wait enough for input with new IDELAY value to
- // propagate through pipeline stages.
- localparam IDEL_SET_VAL = 3'b111;
- // # of clock cycles to delay read enable to determine if read data pattern
- // is correct for stage 3/4 (RDEN, DQS gate) calibration
- localparam CALIB_RDEN_PIPE_LEN = 31;
- // translate CAS latency into number of clock cycles for read valid delay
- // determination. Really only needed for CL = 2.5 (set to 2)
- localparam CAS_LAT_RDEN = (CAS_LAT == 25) ? 2 : CAS_LAT;
- // an SRL32 is used to delay CTRL_RDEN to generate read valid signal. This
- // is min possible value delay through SRL32 can be
- localparam RDEN_BASE_DELAY = CAS_LAT_RDEN + ADDITIVE_LAT + REG_ENABLE;
- // an SRL32 is used to delay the CTRL_RDEN from the read postamble DQS
- // gate. This is min possible value the SRL32 delay can be:
- // - Delay from end of deassertion of CTRL_RDEN to last falling edge of
- // read burst = 3.5 (CTRL_RDEN -> CAS delay) + 3 (min CAS latency) = 6.5
- // - Minimum time for DQS gate circuit to be generated:
- // * 1 cyc to register CTRL_RDEN from controller
- // * 1 cyc after RDEN_CTRL falling edge
- // * 1 cyc min through SRL32
- // * 1 cyc through SRL32 output flop
- // * 0 (<1) cyc of synchronization to DQS domain via IDELAY
- // * 1 cyc of delay through IDDR to generate CE to DQ IDDR's
- // Total = 5 cyc < 6.5 cycles
- // The total should be less than 5.5 cycles to account prop delays
- // adding one cycle to the synchronization time via the IDELAY.
- // NOTE: Value differs because of optional pipeline register added
- // for case of RDEN_BASE_DELAY > 3 to improve timing
- localparam GATE_BASE_DELAY = RDEN_BASE_DELAY - 3;
- localparam GATE_BASE_INIT = (GATE_BASE_DELAY <= 1) ? 0 : GATE_BASE_DELAY;
- // used for RDEN calibration: difference between shift value used during
- // calibration, and shift value for actual RDEN SRL. Only applies when
- // RDEN edge is immediately captured by CLKDIV0. If not (depends on phase
- // of CLK0 and CLKDIV0 when RDEN is asserted), then add 1 to this value.
- localparam CAL3_RDEN_SRL_DLY_DELTA = 6;
- // fix minimum value of DQS to be 1 to handle the case where's there's only
- // one DQS group. We could also enforce that user always inputs minimum
- // value of 1 for DQS_BITS (even when DQS_WIDTH=1). Leave this as safeguard
- // Assume we don't have to do this for DQ, DQ_WIDTH always > 1
- localparam DQS_BITS_FIX = (DQS_BITS == 0) ? 1 : DQS_BITS;
- // how many taps to "pre-delay" DQ before stg 1 calibration - not needed for
- // current calibration, but leave for debug
- localparam DQ_IDEL_INIT = 6'b000000;
- // # IDELAY taps per bit time (i.e. half cycle). Limit to 63.
- localparam integer BIT_TIME_TAPS = (CLK_PERIOD/150 < 64) ?
- CLK_PERIOD/150 : 63;
-
- // used in various places during stage 4 cal: (1) determines maximum taps
- // to increment when finding right edge, (2) amount to decrement after
- // finding left edge, (3) amount to increment after finding right edge
- localparam CAL4_IDEL_BIT_VAL = (BIT_TIME_TAPS >= 6'b100000) ?
- 6'b100000 : BIT_TIME_TAPS;
-
- localparam CAL1_IDLE = 4'h0;
- localparam CAL1_INIT = 4'h1;
- localparam CAL1_INC_IDEL = 4'h2;
- localparam CAL1_FIND_FIRST_EDGE = 4'h3;
- localparam CAL1_FIRST_EDGE_IDEL_WAIT = 4'h4;
- localparam CAL1_FOUND_FIRST_EDGE_WAIT = 4'h5;
- localparam CAL1_FIND_SECOND_EDGE = 4'h6;
- localparam CAL1_SECOND_EDGE_IDEL_WAIT = 4'h7;
- localparam CAL1_CALC_IDEL = 4'h8;
- localparam CAL1_DEC_IDEL = 4'h9;
- localparam CAL1_DONE = 4'hA;
-
- localparam CAL2_IDLE = 4'h0;
- localparam CAL2_INIT = 4'h1;
- localparam CAL2_INIT_IDEL_WAIT = 4'h2;
- localparam CAL2_FIND_EDGE_POS = 4'h3;
- localparam CAL2_FIND_EDGE_IDEL_WAIT_POS = 4'h4;
- localparam CAL2_FIND_EDGE_NEG = 4'h5;
- localparam CAL2_FIND_EDGE_IDEL_WAIT_NEG = 4'h6;
- localparam CAL2_DEC_IDEL = 4'h7;
- localparam CAL2_DONE = 4'h8;
-
- localparam CAL3_IDLE = 3'h0;
- localparam CAL3_INIT = 3'h1;
- localparam CAL3_DETECT = 3'h2;
- localparam CAL3_RDEN_PIPE_CLR_WAIT = 3'h3;
- localparam CAL3_DONE = 3'h4;
-
- localparam CAL4_IDLE = 3'h0;
- localparam CAL4_INIT = 3'h1;
- localparam CAL4_FIND_WINDOW = 3'h2;
- localparam CAL4_FIND_EDGE = 3'h3;
- localparam CAL4_IDEL_WAIT = 3'h4;
- localparam CAL4_RDEN_PIPE_CLR_WAIT = 3'h5;
- localparam CAL4_ADJ_IDEL = 3'h6;
- localparam CAL4_DONE = 3'h7;
-
- integer i, j;
-
- reg [5:0] cal1_bit_time_tap_cnt;
- reg [1:0] cal1_data_chk_last;
- reg cal1_data_chk_last_valid;
- reg [1:0] cal1_data_chk_r;
- reg cal1_dlyce_dq;
- reg cal1_dlyinc_dq;
- reg cal1_dqs_dq_init_phase;
- reg cal1_detect_edge;
- reg cal1_detect_stable;
- reg cal1_found_second_edge;
- reg cal1_found_rising;
- reg cal1_found_window;
- reg cal1_first_edge_done;
- reg [5:0] cal1_first_edge_tap_cnt;
- reg [6:0] cal1_idel_dec_cnt;
- reg [5:0] cal1_idel_inc_cnt;
- reg [5:0] cal1_idel_max_tap;
- reg cal1_idel_max_tap_we;
- reg [5:0] cal1_idel_tap_cnt;
- reg cal1_idel_tap_limit_hit;
- reg [6:0] cal1_low_freq_idel_dec;
- reg cal1_ref_req;
- wire cal1_refresh;
- reg [3:0] cal1_state;
- reg [3:0] cal1_window_cnt;
- reg cal2_curr_sel;
- wire cal2_detect_edge;
- reg cal2_dlyce_dqs;
- reg cal2_dlyinc_dqs;
- reg [5:0] cal2_idel_dec_cnt;
- reg [5:0] cal2_idel_tap_cnt;
- reg [5:0] cal2_idel_tap_limit;
- reg cal2_idel_tap_limit_hit;
- reg cal2_rd_data_fall_last_neg;
- reg cal2_rd_data_fall_last_pos;
- reg cal2_rd_data_last_valid_neg;
- reg cal2_rd_data_last_valid_pos;
- reg cal2_rd_data_rise_last_neg;
- reg cal2_rd_data_rise_last_pos;
- reg [DQS_WIDTH-1:0] cal2_rd_data_sel;
- wire cal2_rd_data_sel_edge;
- reg [DQS_WIDTH-1:0] cal2_rd_data_sel_r;
- reg cal2_ref_req;
- reg [3:0] cal2_state;
- reg cal3_data_match;
- reg cal3_data_match_stgd;
- wire cal3_data_valid;
- wire cal3_match_found;
- wire [4:0] cal3_rden_dly;
- reg [4:0] cal3_rden_srl_a;
- reg [2:0] cal3_state;
- wire cal4_data_good;
- reg cal4_data_match;
- reg cal4_data_match_stgd;
- wire cal4_data_valid;
- reg cal4_dlyce_gate;
- reg cal4_dlyinc_gate;
- reg cal4_dlyrst_gate;
- reg [4:0] cal4_gate_srl_a;
- reg [5:0] cal4_idel_adj_cnt;
- reg cal4_idel_adj_inc;
- reg cal4_idel_bit_tap;
- reg [5:0] cal4_idel_tap_cnt;
- reg cal4_idel_max_tap;
- reg [4:0] cal4_rden_srl_a;
- reg cal4_ref_req;
- reg cal4_seek_left;
- reg cal4_stable_window;
- reg [2:0] cal4_state;
- reg [3:0] cal4_window_cnt;
- reg [3:0] calib_done_tmp; // only for stg1/2/4
- reg calib_ctrl_gate_pulse_r;
- reg calib_ctrl_rden;
- reg calib_ctrl_rden_r;
- wire calib_ctrl_rden_negedge;
- reg calib_ctrl_rden_negedge_r;
- reg [3:0] calib_done_r;
- reg [3:0] calib_err;
- reg [1:0] calib_err_2;
- wire calib_init_gate_pulse;
- reg calib_init_gate_pulse_r;
- reg calib_init_gate_pulse_r1;
- reg calib_init_rden;
- reg calib_init_rden_r;
- reg [4:0] calib_rden_srl_a;
- wire [4:0] calib_rden_srl_a_r;
- reg [(5*DQS_WIDTH)-1:0] calib_rden_dly;
- reg calib_rden_edge_r;
- reg [4:0] calib_rden_pipe_cnt;
- wire calib_rden_srl_out;
- wire calib_rden_srl_out_r;
- reg calib_rden_srl_out_r1;
- reg calib_rden_valid;
- reg calib_rden_valid_stgd;
- reg [DQ_BITS-1:0] count_dq;
- reg [DQS_BITS_FIX-1:0] count_dqs;
- reg [DQS_BITS_FIX-1:0] count_gate;
- reg [DQS_BITS_FIX-1:0] count_rden;
- reg ctrl_rden_r;
- wire dlyce_or;
- reg [(5*DQS_WIDTH)-1:0] gate_dly;
- wire [(5*DQS_WIDTH)-1:0] gate_dly_r;
- wire gate_srl_in;
- wire [DQS_WIDTH-1:0] gate_srl_out;
- wire [DQS_WIDTH-1:0] gate_srl_out_r;
- reg [2:0] idel_set_cnt;
- wire idel_set_wait;
- reg [DQ_BITS-1:0] next_count_dq;
- reg [DQS_BITS_FIX-1:0] next_count_dqs;
- reg [DQS_BITS_FIX-1:0] next_count_gate;
- reg phy_init_rden_r;
- reg phy_init_rden_r1;
- reg [DQS_WIDTH-1:0] rd_data_fall_1x_bit1_r1;
- reg [DQ_WIDTH-1:0] rd_data_fall_1x_r;
- reg [DQS_WIDTH-1:0] rd_data_fall_1x_r1;
- reg [DQS_WIDTH-1:0] rd_data_fall_2x_bit1_r;
- reg [DQS_WIDTH-1:0] rd_data_fall_2x_r;
- wire [DQS_WIDTH-1:0] rd_data_fall_chk_q1;
- wire [DQS_WIDTH-1:0] rd_data_fall_chk_q1_bit1;
- wire [DQS_WIDTH-1:0] rd_data_fall_chk_q2;
- wire [DQS_WIDTH-1:0] rd_data_fall_chk_q2_bit1;
- reg [DQS_WIDTH-1:0] rd_data_rise_1x_bit1_r1;
- reg [DQ_WIDTH-1:0] rd_data_rise_1x_r;
- reg [DQS_WIDTH-1:0] rd_data_rise_1x_r1;
- reg [DQS_WIDTH-1:0] rd_data_rise_2x_bit1_r;
- reg [DQS_WIDTH-1:0] rd_data_rise_2x_r;
- wire [DQS_WIDTH-1:0] rd_data_rise_chk_q1;
- wire [DQS_WIDTH-1:0] rd_data_rise_chk_q1_bit1;
- wire [DQS_WIDTH-1:0] rd_data_rise_chk_q2;
- wire [DQS_WIDTH-1:0] rd_data_rise_chk_q2_bit1;
- reg rdd_fall_q1;
- reg rdd_fall_q1_bit1;
- reg rdd_fall_q1_bit1_r;
- reg rdd_fall_q1_bit1_r1;
- reg rdd_fall_q1_r;
- reg rdd_fall_q1_r1;
- reg rdd_fall_q2;
- reg rdd_fall_q2_bit1;
- reg rdd_fall_q2_bit1_r;
- reg rdd_fall_q2_r;
- reg rdd_rise_q1;
- reg rdd_rise_q1_bit1;
- reg rdd_rise_q1_bit1_r;
- reg rdd_rise_q1_bit1_r1;
- reg rdd_rise_q1_r;
- reg rdd_rise_q1_r1;
- reg rdd_rise_q2;
- reg rdd_rise_q2_bit1;
- reg rdd_rise_q2_bit1_r;
- reg rdd_rise_q2_r;
- reg [DQS_BITS_FIX-1:0] rdd_mux_sel;
- reg rden_dec;
- reg [(5*DQS_WIDTH)-1:0] rden_dly;
- wire [(5*DQS_WIDTH)-1:0] rden_dly_r;
- reg [4:0] rden_dly_0;
- reg rden_inc;
- reg [DQS_WIDTH-1:0] rden_mux;
- wire [DQS_WIDTH-1:0] rden_srl_out;
-
- // Debug
- integer x;
- reg [5:0] dbg_dq_tap_cnt [DQ_WIDTH-1:0];
- reg [5:0] dbg_dqs_tap_cnt [DQS_WIDTH-1:0];
- reg [5:0] dbg_gate_tap_cnt [DQS_WIDTH-1:0];
-
- //***************************************************************************
- // Debug output ("dbg_phy_calib_*")
- // NOTES:
- // 1. All debug outputs coming out of PHY_CALIB are clocked off CLKDIV0,
- // although they are also static after calibration is complete. This
- // means the user can either connect them to a Chipscope ILA, or to
- // either a sync/async VIO input block. Using an async VIO has the
- // advantage of not requiring these paths to meet cycle-to-cycle timing.
- // 2. The widths of most of these debug buses are dependent on the # of
- // DQS/DQ bits (e.g. dq_tap_cnt width = 6 * (# of DQ bits)
- // SIGNAL DESCRIPTION:
- // 1. calib_done: 4 bits - each one asserted as each phase of calibration
- // is completed.
- // 2. calib_err: 4 bits - each one asserted when a calibration error
- // encountered for that stage. Some of these bits may not
- // be used (not all cal stages report an error).
- // 3. dq_tap_cnt: final IDELAY tap counts for all DQ IDELAYs
- // 4. dqs_tap_cnt: final IDELAY tap counts for all DQS IDELAYs
- // 5. gate_tap_cnt: final IDELAY tap counts for all DQS gate
- // synchronization IDELAYs
- // 6. rd_data_sel: final read capture MUX (either "positive" or "negative"
- // edge capture) settings for all DQS groups
- // 7. rden_dly: related to # of cycles after issuing a read until when
- // read data is valid - for all DQS groups
- // 8. gate_dly: related to # of cycles after issuing a read until when
- // clock enable for all DQ's is deasserted to prevent
- // effect of DQS postamble glitch - for all DQS groups
- //***************************************************************************
-
- //*****************************************************************
- // Record IDELAY tap values by "snooping" IDELAY control signals
- //*****************************************************************
-
- // record DQ IDELAY tap values
- genvar dbg_dq_tc_i;
- generate
- for (dbg_dq_tc_i = 0; dbg_dq_tc_i < DQ_WIDTH;
- dbg_dq_tc_i = dbg_dq_tc_i + 1) begin: gen_dbg_dq_tap_cnt
- assign dbg_calib_dq_tap_cnt[(6*dbg_dq_tc_i)+5:(6*dbg_dq_tc_i)]
- = dbg_dq_tap_cnt[dbg_dq_tc_i];
- always @(posedge clkdiv)
- if (rstdiv | dlyrst_dq)
- dbg_dq_tap_cnt[dbg_dq_tc_i] <= 6'b000000;
- else
- if (dlyce_dq[dbg_dq_tc_i])
- if (dlyinc_dq[dbg_dq_tc_i])
- dbg_dq_tap_cnt[dbg_dq_tc_i]
- <= dbg_dq_tap_cnt[dbg_dq_tc_i] + 1;
- else
- dbg_dq_tap_cnt[dbg_dq_tc_i]
- <= dbg_dq_tap_cnt[dbg_dq_tc_i] - 1;
- end
- endgenerate
-
- // record DQS IDELAY tap values
- genvar dbg_dqs_tc_i;
- generate
- for (dbg_dqs_tc_i = 0; dbg_dqs_tc_i < DQS_WIDTH;
- dbg_dqs_tc_i = dbg_dqs_tc_i + 1) begin: gen_dbg_dqs_tap_cnt
- assign dbg_calib_dqs_tap_cnt[(6*dbg_dqs_tc_i)+5:(6*dbg_dqs_tc_i)]
- = dbg_dqs_tap_cnt[dbg_dqs_tc_i];
- always @(posedge clkdiv)
- if (rstdiv | dlyrst_dqs)
- dbg_dqs_tap_cnt[dbg_dqs_tc_i] <= 6'b000000;
- else
- if (dlyce_dqs[dbg_dqs_tc_i])
- if (dlyinc_dqs[dbg_dqs_tc_i])
- dbg_dqs_tap_cnt[dbg_dqs_tc_i]
- <= dbg_dqs_tap_cnt[dbg_dqs_tc_i] + 1;
- else
- dbg_dqs_tap_cnt[dbg_dqs_tc_i]
- <= dbg_dqs_tap_cnt[dbg_dqs_tc_i] - 1;
- end
- endgenerate
-
- // record DQS gate IDELAY tap values
- genvar dbg_gate_tc_i;
- generate
- for (dbg_gate_tc_i = 0; dbg_gate_tc_i < DQS_WIDTH;
- dbg_gate_tc_i = dbg_gate_tc_i + 1) begin: gen_dbg_gate_tap_cnt
- assign dbg_calib_gate_tap_cnt[(6*dbg_gate_tc_i)+5:(6*dbg_gate_tc_i)]
- = dbg_gate_tap_cnt[dbg_gate_tc_i];
- always @(posedge clkdiv)
- if (rstdiv | dlyrst_gate[dbg_gate_tc_i])
- dbg_gate_tap_cnt[dbg_gate_tc_i] <= 6'b000000;
- else
- if (dlyce_gate[dbg_gate_tc_i])
- if (dlyinc_gate[dbg_gate_tc_i])
- dbg_gate_tap_cnt[dbg_gate_tc_i]
- <= dbg_gate_tap_cnt[dbg_gate_tc_i] + 1;
- else
- dbg_gate_tap_cnt[dbg_gate_tc_i]
- <= dbg_gate_tap_cnt[dbg_gate_tc_i] - 1;
- end
- endgenerate
-
- assign dbg_calib_done = calib_done;
- assign dbg_calib_err = calib_err;
- assign dbg_calib_rd_data_sel = cal2_rd_data_sel;
- assign dbg_calib_rden_dly = rden_dly;
- assign dbg_calib_gate_dly = gate_dly;
-
- //***************************************************************************
- // Read data pipelining, and read data "ISERDES" data width expansion
- //***************************************************************************
-
- // For all data bits, register incoming capture data to slow clock to improve
- // timing. Adding single pipeline stage does not affect functionality (as
- // long as we make sure to wait extra clock cycle after changing DQ IDELAY)
- // Also note in this case that we're "missing" every other clock cycle's
- // worth of data capture since we're sync'ing to the slow clock. This is
- // fine for stage 1 and stage 2 cal, but not for stage 3 and 4 (see below
- // for different circuit to handle those stages)
- always @(posedge clkdiv) begin
- rd_data_rise_1x_r <= rd_data_rise;
- rd_data_fall_1x_r <= rd_data_fall;
- end
-
- // For every DQ_PER_DQS bit, generate what is essentially a ISERDES-type
- // data width expander. Will need this for stage 3 and 4 cal, where we need
- // to compare data over consecutive clock cycles. We can also use this for
- // stage 2 as well (stage 2 doesn't require every bit to be looked at, only
- // one bit per DQS group)
- // MIG 3.3: Expand to use lower two bits of each DQS group - use for stage
- // 3 calibration for added robustness, since we will be checking for the
- // training pattern from the memory even when the data bus is 3-stated.
- // Theoretically it is possible for whatever garbage data is on the bus
- // to be interpreted as the training sequence, although this can be made
- // very unlikely by the choice of training sequence (bit sequence, length)
- // and the number of bits compared for each DQS group.
- genvar rdd_i;
- generate
- for (rdd_i = 0; rdd_i < DQS_WIDTH; rdd_i = rdd_i + 1) begin: gen_rdd
- // first stage: keep data in fast clk domain. Store data over two
- // consecutive clock cycles for rise/fall data for proper transfer
- // to slow clock domain
- always @(posedge clk) begin
- rd_data_rise_2x_r[rdd_i] <= rd_data_rise[(rdd_i*DQ_PER_DQS)];
- rd_data_fall_2x_r[rdd_i] <= rd_data_fall[(rdd_i*DQ_PER_DQS)];
- rd_data_rise_2x_bit1_r[rdd_i] <= rd_data_rise[(rdd_i*DQ_PER_DQS)+1];
- rd_data_fall_2x_bit1_r[rdd_i] <= rd_data_fall[(rdd_i*DQ_PER_DQS)+1];
- end
- // second stage, register first stage to slow clock domain, 2nd stage
- // consists of both these flops, and the rd_data_rise_1x_r flops
- always @(posedge clkdiv) begin
- rd_data_rise_1x_r1[rdd_i] <= rd_data_rise_2x_r[rdd_i];
- rd_data_fall_1x_r1[rdd_i] <= rd_data_fall_2x_r[rdd_i];
- rd_data_rise_1x_bit1_r1[rdd_i] <= rd_data_rise_2x_bit1_r[rdd_i];
- rd_data_fall_1x_bit1_r1[rdd_i] <= rd_data_fall_2x_bit1_r[rdd_i];
- end
- // now we have four outputs - representing rise/fall outputs over last
- // 2 fast clock cycles. However, the ordering these represent can either
- // be: (1) Q2 = data @ time = n, Q1 = data @ time = n+1, or (2)
- // Q2 = data @ time = n - 1, Q1 = data @ time = n (and data at [Q1,Q2]
- // is "staggered") - leave it up to the stage of calibration using this
- // to figure out which is which, if they care at all (e.g. stage 2 cal
- // doesn't care about the ordering)
- assign rd_data_rise_chk_q1[rdd_i]
- = rd_data_rise_1x_r[(rdd_i*DQ_PER_DQS)];
- assign rd_data_rise_chk_q2[rdd_i]
- = rd_data_rise_1x_r1[rdd_i];
- assign rd_data_fall_chk_q1[rdd_i]
- = rd_data_fall_1x_r[(rdd_i*DQ_PER_DQS)];
- assign rd_data_fall_chk_q2[rdd_i]
- = rd_data_fall_1x_r1[rdd_i];
- // MIG 3.3: Added comparison for second bit in DQS group for stage 3 cal
- assign rd_data_rise_chk_q1_bit1[rdd_i]
- = rd_data_rise_1x_r[(rdd_i*DQ_PER_DQS)+1];
- assign rd_data_rise_chk_q2_bit1[rdd_i]
- = rd_data_rise_1x_bit1_r1[rdd_i];
- assign rd_data_fall_chk_q1_bit1[rdd_i]
- = rd_data_fall_1x_r[(rdd_i*DQ_PER_DQS)+1];
- assign rd_data_fall_chk_q2_bit1[rdd_i]
- = rd_data_fall_1x_bit1_r1[rdd_i];
- end
- endgenerate
-
- //*****************************************************************
- // Outputs of these simplified ISERDES circuits then feed MUXes based on
- // which DQ the current calibration algorithm needs to look at
- //*****************************************************************
-
- // generate MUX control; assume that adding an extra pipeline stage isn't
- // an issue - whatever stage cal logic is using output of MUX will wait
- // enough time after changing it
- always @(posedge clkdiv) begin
- (* full_case, parallel_case *) case (calib_done[2:0])
- 3'b001: rdd_mux_sel <= next_count_dqs;
- 3'b011: rdd_mux_sel <= count_rden;
- 3'b111: rdd_mux_sel <= next_count_gate;
- default: rdd_mux_sel <= {DQS_BITS_FIX{1'bx}};
- endcase
- end
-
- always @(posedge clkdiv) begin
- rdd_rise_q1 <= rd_data_rise_chk_q1[rdd_mux_sel];
- rdd_rise_q2 <= rd_data_rise_chk_q2[rdd_mux_sel];
- rdd_fall_q1 <= rd_data_fall_chk_q1[rdd_mux_sel];
- rdd_fall_q2 <= rd_data_fall_chk_q2[rdd_mux_sel];
- rdd_rise_q1_bit1 <= rd_data_rise_chk_q1_bit1[rdd_mux_sel];
- rdd_rise_q2_bit1 <= rd_data_rise_chk_q2_bit1[rdd_mux_sel];
- rdd_fall_q1_bit1 <= rd_data_fall_chk_q1_bit1[rdd_mux_sel];
- rdd_fall_q2_bit1 <= rd_data_fall_chk_q2_bit1[rdd_mux_sel];
- end
-
- //***************************************************************************
- // Demultiplexor to control (reset, increment, decrement) IDELAY tap values
- // For DQ:
- // STG1: for per-bit-deskew, only inc/dec the current DQ. For non-per
- // deskew, increment all bits in the current DQS set
- // STG2: inc/dec all DQ's in the current DQS set.
- // NOTE: Nice to add some error checking logic here (or elsewhere in the
- // code) to check if logic attempts to overflow tap value
- //***************************************************************************
-
- // don't use DLYRST to reset value of IDELAY after reset. Need to change this
- // if we want to allow user to recalibrate after initial reset
- always @(posedge clkdiv)
- if (rstdiv) begin
- dlyrst_dq <= 1'b1;
- dlyrst_dqs <= 1'b1;
- end else begin
- dlyrst_dq <= 1'b0;
- dlyrst_dqs <= 1'b0;
- end
-
- always @(posedge clkdiv) begin
- if (rstdiv) begin
- dlyce_dq <= 'b0;
- dlyinc_dq <= 'b0;
- dlyce_dqs <= 'b0;
- dlyinc_dqs <= 'b0;
- end else begin
- dlyce_dq <= 'b0;
- dlyinc_dq <= 'b0;
- dlyce_dqs <= 'b0;
- dlyinc_dqs <= 'b0;
-
- // stage 1 cal: change only specified DQ
- if (cal1_dlyce_dq) begin
- if (SIM_ONLY == 0) begin
- dlyce_dq[count_dq] <= 1'b1;
- dlyinc_dq[count_dq] <= cal1_dlyinc_dq;
- end else begin
- // if simulation, then calibrate only first DQ, apply results
- // to all DQs (i.e. assume delay on all DQs is the same)
- for (i = 0; i < DQ_WIDTH; i = i + 1) begin: loop_sim_dq_dly
- dlyce_dq[i] <= 1'b1;
- dlyinc_dq[i] <= cal1_dlyinc_dq;
- end
- end
- end else if (cal2_dlyce_dqs) begin
- // stage 2 cal: change DQS and all corresponding DQ's
- if (SIM_ONLY == 0) begin
- dlyce_dqs[count_dqs] <= 1'b1;
- dlyinc_dqs[count_dqs] <= cal2_dlyinc_dqs;
- for (i = 0; i < DQ_PER_DQS; i = i + 1) begin: loop_dqs_dly
- dlyce_dq[(DQ_PER_DQS*count_dqs)+i] <= 1'b1;
- dlyinc_dq[(DQ_PER_DQS*count_dqs)+i] <= cal2_dlyinc_dqs;
- end
- end else begin
- for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_dqs_dly
- // if simulation, then calibrate only first DQS
- dlyce_dqs[i] <= 1'b1;
- dlyinc_dqs[i] <= cal2_dlyinc_dqs;
- for (j = 0; j < DQ_PER_DQS; j = j + 1) begin: loop_sim_dq_dqs_dly
- dlyce_dq[(DQ_PER_DQS*i)+j] <= 1'b1;
- dlyinc_dq[(DQ_PER_DQS*i)+j] <= cal2_dlyinc_dqs;
- end
- end
- end
- end else if (DEBUG_EN != 0) begin
- // DEBUG: allow user to vary IDELAY tap settings
- // For DQ IDELAY taps
- if (dbg_idel_up_all || dbg_idel_down_all ||
- dbg_sel_all_idel_dq) begin
- for (x = 0; x < DQ_WIDTH; x = x + 1) begin: loop_dly_inc_dq
- dlyce_dq[x] <= dbg_idel_up_all | dbg_idel_down_all |
- dbg_idel_up_dq | dbg_idel_down_dq;
- dlyinc_dq[x] <= dbg_idel_up_all | dbg_idel_up_dq;
- end
- end else begin
- dlyce_dq <= 'b0;
- dlyce_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq |
- dbg_idel_down_dq;
- dlyinc_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq;
- end
- // For DQS IDELAY taps
- if (dbg_idel_up_all || dbg_idel_down_all ||
- dbg_sel_all_idel_dqs) begin
- for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_dqs
- dlyce_dqs[x] <= dbg_idel_up_all | dbg_idel_down_all |
- dbg_idel_up_dqs | dbg_idel_down_dqs;
- dlyinc_dqs[x] <= dbg_idel_up_all | dbg_idel_up_dqs;
- end
- end else begin
- dlyce_dqs <= 'b0;
- dlyce_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs |
- dbg_idel_down_dqs;
- dlyinc_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs;
- end
- end
- end
- end
-
- // GATE synchronization is handled directly by Stage 4 calibration FSM
- always @(posedge clkdiv)
- if (rstdiv) begin
- dlyrst_gate <= {DQS_WIDTH{1'b1}};
- dlyce_gate <= {DQS_WIDTH{1'b0}};
- dlyinc_gate <= {DQS_WIDTH{1'b0}};
- end else begin
- dlyrst_gate <= {DQS_WIDTH{1'b0}};
- dlyce_gate <= {DQS_WIDTH{1'b0}};
- dlyinc_gate <= {DQS_WIDTH{1'b0}};
-
- if (cal4_dlyrst_gate) begin
- if (SIM_ONLY == 0)
- dlyrst_gate[count_gate] <= 1'b1;
- else
- for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly_rst
- dlyrst_gate[i] <= 1'b1;
- end
- end
-
- if (cal4_dlyce_gate) begin
- if (SIM_ONLY == 0) begin
- dlyce_gate[count_gate] <= 1'b1;
- dlyinc_gate[count_gate] <= cal4_dlyinc_gate;
- end else begin
- // if simulation, then calibrate only first gate
- for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly
- dlyce_gate[i] <= 1'b1;
- dlyinc_gate[i] <= cal4_dlyinc_gate;
- end
- end
- end else if (DEBUG_EN != 0) begin
- // DEBUG: allow user to vary IDELAY tap settings
- if (dbg_idel_up_all || dbg_idel_down_all ||
- dbg_sel_all_idel_gate) begin
- for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_gate
- dlyce_gate[x] <= dbg_idel_up_all | dbg_idel_down_all |
- dbg_idel_up_gate | dbg_idel_down_gate;
- dlyinc_gate[x] <= dbg_idel_up_all | dbg_idel_up_gate;
- end
- end else begin
- dlyce_gate <= {DQS_WIDTH{1'b0}};
- dlyce_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate |
- dbg_idel_down_gate;
- dlyinc_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate;
- end
- end
- end
-
- //***************************************************************************
- // signal to tell calibration state machines to wait and give IDELAY time to
- // settle after it's value is changed (both time for IDELAY chain to settle,
- // and for settled output to propagate through ISERDES). For general use: use
- // for any calibration state machines that modify any IDELAY.
- // Should give at least enough time for IDELAY output to settle (technically
- // for V5, this should be "glitchless" when IDELAY taps are changed, so don't
- // need any time here), and also time for new data to propagate through both
- // ISERDES and the "RDD" MUX + associated pipelining
- // For now, give very "generous" delay - doesn't really matter since only
- // needed during calibration
- //***************************************************************************
-
- // determine if calibration polarity has changed
- always @(posedge clkdiv)
- cal2_rd_data_sel_r <= cal2_rd_data_sel;
-
- assign cal2_rd_data_sel_edge = |(cal2_rd_data_sel ^ cal2_rd_data_sel_r);
-
- // combine requests to modify any of the IDELAYs into one. Also when second
- // stage capture "edge" polarity is changed (IDELAY isn't changed in this
- // case, but use the same counter to stall cal logic)
- assign dlyce_or = cal1_dlyce_dq |
- cal2_dlyce_dqs |
- cal2_rd_data_sel_edge |
- cal4_dlyce_gate |
- cal4_dlyrst_gate;
-
- // SYN_NOTE: Can later recode to avoid combinational path
- assign idel_set_wait = dlyce_or || (idel_set_cnt != IDEL_SET_VAL);
-
- always @(posedge clkdiv)
- if (rstdiv)
- idel_set_cnt <= 4'b0000;
- else if (dlyce_or)
- idel_set_cnt <= 4'b0000;
- else if (idel_set_cnt != IDEL_SET_VAL)
- idel_set_cnt <= idel_set_cnt + 1;
-
- // generate request to PHY_INIT logic to issue auto-refresh
- // used by certain states to force prech/auto-refresh part way through
- // calibration to avoid a tRAS violation (which will happen if that
- // stage of calibration lasts long enough). This signal must meet the
- // following requirements: (1) only transition from 0->1 when the refresh
- // request is needed, (2) stay at 1 and only transition 1->0 when
- // CALIB_REF_DONE is asserted
- always @(posedge clkdiv)
- if (rstdiv)
- calib_ref_req <= 1'b0;
- else
- calib_ref_req <= cal1_ref_req | cal2_ref_req | cal4_ref_req;
-
- // stage 1 calibration requests auto-refresh every 4 bits
- generate
- if (DQ_BITS < 2) begin: gen_cal1_refresh_dq_lte4
- assign cal1_refresh = 1'b0;
- end else begin: gen_cal1_refresh_dq_gt4
- assign cal1_refresh = (next_count_dq[1:0] == 2'b00);
- end
- endgenerate
-
- //***************************************************************************
- // First stage calibration: DQ-DQS
- // Definitions:
- // edge: detected when varying IDELAY, and current capture data != prev
- // capture data
- // valid bit window: detected when current capture data == prev capture
- // data for more than half the bit time
- // starting conditions for DQS-DQ phase:
- // case 1: when DQS starts somewhere in rising edge bit window, or
- // on the right edge of the rising bit window.
- // case 2: when DQS starts somewhere in falling edge bit window, or
- // on the right edge of the falling bit window.
- // Algorithm Description:
- // 1. Increment DQ IDELAY until we find an edge.
- // 2. While we're finding the first edge, note whether a valid bit window
- // has been detected before we found an edge. If so, then figure out if
- // this is the rising or falling bit window. If rising, then our starting
- // DQS-DQ phase is case 1. If falling, then it's case 2. If don't detect
- // a valid bit window, then we must have started on the edge of a window.
- // Need to wait until later on to decide which case we are.
- // - Store FIRST_EDGE IDELAY value
- // 3. Now look for second edge.
- // 4. While we're finding the second edge, note whether valid bit window
- // is detected. If so, then use to, along with results from (2) to figure
- // out what the starting case is. If in rising bit window, then we're in
- // case 2. If falling, then case 1.
- // - Store SECOND_EDGE IDELAY value
- // NOTES:
- // a. Finding two edges allows us to calculate the bit time (although
- // not the "same" bit time polarity - need to investigate this
- // more).
- // b. If we run out of taps looking for the second edge, then the bit
- // time must be too long (>= 2.5ns, and DQS-DQ starting phase must be
- // case 1).
- // 5. Calculate absolute amount to delay DQ as:
- // If second edge found, and case 1:
- // - DQ_IDELAY = FIRST_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
- // If second edge found, and case 2:
- // - DQ_IDELAY = SECOND_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
- // If second edge not found, then need to make an approximation on
- // how much to shift by (should be okay, because we have more timing
- // margin):
- // - DQ_IDELAY = FIRST_EDGE - 0.5 * (bit_time)
- // NOTE: Does this account for either case 1 or case 2?????
- // NOTE: It's also possible even when we find the second edge, that
- // to instead just use half the bit time to subtract from either
- // FIRST or SECOND_EDGE. Finding the actual bit time (which is
- // what (SECOND_EDGE - FIRST_EDGE) is, is slightly more accurate,
- // since it takes into account duty cycle distortion.
- // 6. Repeat for each DQ in current DQS set.
- //***************************************************************************
-
- //*****************************************************************
- // for first stage calibration - used for checking if DQS is aligned to the
- // particular DQ, such that we're in the data valid window. Basically, this
- // is one giant MUX.
- // = [falling data, rising data]
- // = [0, 1] = rising DQS aligned in proper (rising edge) bit window
- // = [1, 0] = rising DQS aligned in wrong (falling edge) bit window
- // = [0, 0], or [1,1] = in uncertain region between windows
- //*****************************************************************
-
- // SYN_NOTE: May have to split this up into multiple levels - MUX can get
- // very wide - as wide as the data bus width
- always @(posedge clkdiv)
- cal1_data_chk_r <= {rd_data_fall_1x_r[next_count_dq],
- rd_data_rise_1x_r[next_count_dq]};
-
- //*****************************************************************
- // determine when an edge has occurred - when either the current value
- // is different from the previous latched value or when the DATA_CHK
- // outputs are the same (rare, but indicates that we're at an edge)
- // This is only valid when the IDELAY output and propagation of the
- // data through the capture flops has had a chance to settle out.
- //*****************************************************************
-
- // write CAL1_DETECT_EDGE and CAL1_DETECT_STABLE in such a way that
- // if X's are captured on the bus during functional simulation, that
- // the logic will register this as an edge detected. Do this to allow
- // use of this HDL with Denali memory models (Denali models drive DQ
- // to X's on both edges of the data valid window to simulate jitter)
- // This is only done for functional simulation purposes. **Should not**
- // make the final synthesized logic more complicated, but it does make
- // the HDL harder to understand b/c we have to "phrase" the logic
- // slightly differently than when not worrying about X's
- always @(*) begin
- // no edge found if: (1) we have recorded prev edge, and rise
- // data == fall data, (2) we haven't yet recorded prev edge, but
- // rise/fall data is equal to either [0,1] or [1,0] (i.e. rise/fall
- // data isn't either X's, or [0,0] or [1,1], which indicates we're
- // in the middle of an edge, since normally rise != fall data for stg1)
- if ((cal1_data_chk_last_valid &&
- (cal1_data_chk_r == cal1_data_chk_last)) ||
- (!cal1_data_chk_last_valid &&
- ((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10))))
- cal1_detect_edge = 1'b0;
- else
- cal1_detect_edge = 1'b1;
- end
-
- always @(*) begin
- // assert if we've found a region where data valid window is stable
- // over consecutive IDELAY taps, and either rise/fall = [1,0], or [0,1]
- if ((cal1_data_chk_last_valid &&
- (cal1_data_chk_r == cal1_data_chk_last)) &&
- ((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10)))
- cal1_detect_stable = 1'b1;
- else
- cal1_detect_stable = 1'b0;
- end
-
- //*****************************************************************
- // Find valid window: keep track of how long we've been in the same data
- // window. If it's been long enough, then declare that we've found a valid
- // window. Also returns whether we found a rising or falling window (only
- // valid when found_window is asserted)
- //*****************************************************************
-
- always @(posedge clkdiv) begin
- if (cal1_state == CAL1_INIT) begin
- cal1_window_cnt <= 4'b0000;
- cal1_found_window <= 1'b0;
- cal1_found_rising <= 1'bx;
- end else if (!cal1_data_chk_last_valid) begin
- // if we haven't stored a previous value of CAL1_DATA_CHK (or it got
- // invalidated because we detected an edge, and are now looking for the
- // second edge), then make sure FOUND_WINDOW deasserted on following
- // clock edge (to avoid finding a false window immediately after finding
- // an edge). Note that because of jitter, it's possible to not find an
- // edge at the end of the IDELAY increment settling time, but to find an
- // edge on the next clock cycle (e.g. during CAL1_FIND_FIRST_EDGE)
- cal1_window_cnt <= 4'b0000;
- cal1_found_window <= 1'b0;
- cal1_found_rising <= 1'bx;
- end else if (((cal1_state == CAL1_FIRST_EDGE_IDEL_WAIT) ||
- (cal1_state == CAL1_SECOND_EDGE_IDEL_WAIT)) &&
- !idel_set_wait) begin
- // while finding the first and second edges, see if we can detect a
- // stable bit window (occurs over MIN_WIN_SIZE number of taps). If
- // so, then we're away from an edge, and can conclusively determine the
- // starting DQS-DQ phase.
- if (cal1_detect_stable) begin
- cal1_window_cnt <= cal1_window_cnt + 1;
- if (cal1_window_cnt == MIN_WIN_SIZE-1) begin
- cal1_found_window <= 1'b1;
- if (cal1_data_chk_r == 2'b01)
- cal1_found_rising <= 1'b1;
- else
- cal1_found_rising <= 1'b0;
- end
- end else begin
- // otherwise, we're not in a data valid window, reset the window
- // counter, and indicate we're not currently in window. This should
- // happen by design at least once after finding the first edge.
- cal1_window_cnt <= 4'b0000;
- cal1_found_window <= 1'b0;
- cal1_found_rising <= 1'bx;
- end
- end
- end
-
- //*****************************************************************
- // keep track of edge tap counts found, and whether we've
- // incremented to the maximum number of taps allowed
- //*****************************************************************
-
- always @(posedge clkdiv)
- if (cal1_state == CAL1_INIT) begin
- cal1_idel_tap_limit_hit <= 1'b0;
- cal1_idel_tap_cnt <= 6'b000000;
- end else if (cal1_dlyce_dq) begin
- if (cal1_dlyinc_dq) begin
- cal1_idel_tap_cnt <= cal1_idel_tap_cnt + 1;
- cal1_idel_tap_limit_hit <= (cal1_idel_tap_cnt == 6'b111110);
- end else begin
- cal1_idel_tap_cnt <= cal1_idel_tap_cnt - 1;
- cal1_idel_tap_limit_hit <= 1'b0;
- end
- end
-
- //*****************************************************************
- // Pipeline for better timing - amount to decrement by if second
- // edge not found
- //*****************************************************************
- // if only one edge found (possible for low frequencies), then:
- // 1. Assume starting DQS-DQ phase has DQS in DQ window (aka "case 1")
- // 2. We have to decrement by (63 - first_edge_tap_cnt) + (BIT_TIME_TAPS/2)
- // (i.e. decrement by 63-first_edge_tap_cnt to get to right edge of
- // DQ window. Then decrement again by (BIT_TIME_TAPS/2) to get to center
- // of DQ window.
- // 3. Clamp the above value at 63 to ensure we don't underflow IDELAY
- // (note: clamping happens in the CAL1 state machine)
- always @(posedge clkdiv)
- cal1_low_freq_idel_dec
- <= (7'b0111111 - {1'b0, cal1_first_edge_tap_cnt}) +
- (BIT_TIME_TAPS/2);
-
- //*****************************************************************
- // Keep track of max taps used during stage 1, use this to limit
- // the number of taps that can be used in stage 2
- //*****************************************************************
-
- always @(posedge clkdiv)
- if (rstdiv) begin
- cal1_idel_max_tap <= 6'b000000;
- cal1_idel_max_tap_we <= 1'b0;
- end else begin
- // pipeline latch enable for CAL1_IDEL_MAX_TAP - we have plenty
- // of time, tap count gets updated, then dead cycles waiting for
- // IDELAY output to settle
- cal1_idel_max_tap_we <= (cal1_idel_max_tap < cal1_idel_tap_cnt);
- // record maximum # of taps used for stg 1 cal
- if ((cal1_state == CAL1_DONE) && cal1_idel_max_tap_we)
- cal1_idel_max_tap <= cal1_idel_tap_cnt;
- end
-
- //*****************************************************************
-
- always @(posedge clkdiv)
- if (rstdiv) begin
- calib_done[0] <= 1'b0;
- calib_done_tmp[0] <= 1'bx;
- calib_err[0] <= 1'b0;
- count_dq <= {DQ_BITS{1'b0}};
- next_count_dq <= {DQ_BITS{1'b0}};
- cal1_bit_time_tap_cnt <= 6'bxxxxxx;
- cal1_data_chk_last <= 2'bxx;
- cal1_data_chk_last_valid <= 1'bx;
- cal1_dlyce_dq <= 1'b0;
- cal1_dlyinc_dq <= 1'b0;
- cal1_dqs_dq_init_phase <= 1'bx;
- cal1_first_edge_done <= 1'bx;
- cal1_found_second_edge <= 1'bx;
- cal1_first_edge_tap_cnt <= 6'bxxxxxx;
- cal1_idel_dec_cnt <= 7'bxxxxxxx;
- cal1_idel_inc_cnt <= 6'bxxxxxx;
- cal1_ref_req <= 1'b0;
- cal1_state <= CAL1_IDLE;
- end else begin
- // default values for all "pulse" outputs
- cal1_ref_req <= 1'b0;
- cal1_dlyce_dq <= 1'b0;
- cal1_dlyinc_dq <= 1'b0;
-
- case (cal1_state)
- CAL1_IDLE: begin
- count_dq <= {DQ_BITS{1'b0}};
- next_count_dq <= {DQ_BITS{1'b0}};
- if (calib_start[0]) begin
- calib_done[0] <= 1'b0;
- calib_done_tmp[0] <= 1'b0;
- cal1_state <= CAL1_INIT;
- end
- end
-
- CAL1_INIT: begin
- cal1_data_chk_last_valid <= 1'b0;
- cal1_found_second_edge <= 1'b0;
- cal1_dqs_dq_init_phase <= 1'b0;
- cal1_idel_inc_cnt <= 6'b000000;
- cal1_state <= CAL1_INC_IDEL;
- end
-
- // increment DQ IDELAY so that either: (1) DQS starts somewhere in
- // first rising DQ window, or (2) DQS starts in first falling DQ
- // window. The amount to shift is frequency dependent (and is either
- // precalculated by MIG or possibly adjusted by the user)
- CAL1_INC_IDEL:
- if ((cal1_idel_inc_cnt == DQ_IDEL_INIT) && !idel_set_wait) begin
- cal1_state <= CAL1_FIND_FIRST_EDGE;
- end else if (cal1_idel_inc_cnt != DQ_IDEL_INIT) begin
- cal1_idel_inc_cnt <= cal1_idel_inc_cnt + 1;
- cal1_dlyce_dq <= 1'b1;
- cal1_dlyinc_dq <= 1'b1;
- end
-
- // look for first edge
- CAL1_FIND_FIRST_EDGE: begin
- // Determine DQS-DQ phase if we can detect enough of a valid window
- if (cal1_found_window)
- cal1_dqs_dq_init_phase <= ~cal1_found_rising;
- // find first edge - if found then record position
- if (cal1_detect_edge) begin
- cal1_state <= CAL1_FOUND_FIRST_EDGE_WAIT;
- cal1_first_edge_done <= 1'b0;
- cal1_first_edge_tap_cnt <= cal1_idel_tap_cnt;
- cal1_data_chk_last_valid <= 1'b0;
- end else begin
- // otherwise, store the current value of DATA_CHK, increment
- // DQ IDELAY, and compare again
- cal1_state <= CAL1_FIRST_EDGE_IDEL_WAIT;
- cal1_data_chk_last <= cal1_data_chk_r;
- // avoid comparing against DATA_CHK_LAST for previous iteration
- cal1_data_chk_last_valid <= 1'b1;
- cal1_dlyce_dq <= 1'b1;
- cal1_dlyinc_dq <= 1'b1;
- end
- end
-
- // wait for DQ IDELAY to settle
- CAL1_FIRST_EDGE_IDEL_WAIT:
- if (!idel_set_wait)
- cal1_state <= CAL1_FIND_FIRST_EDGE;
-
- // delay state between finding first edge and looking for second
- // edge. Necessary in order to invalidate CAL1_FOUND_WINDOW before
- // starting to look for second edge
- CAL1_FOUND_FIRST_EDGE_WAIT:
- cal1_state <= CAL1_FIND_SECOND_EDGE;
-
- // Try and find second edge
- CAL1_FIND_SECOND_EDGE: begin
- // When looking for 2nd edge, first make sure data stabilized (by
- // detecting valid data window) - needed to avoid false edges
- if (cal1_found_window) begin
- cal1_first_edge_done <= 1'b1;
- cal1_dqs_dq_init_phase <= cal1_found_rising;
- end
- // exit if run out of taps to increment
- if (cal1_idel_tap_limit_hit)
- cal1_state <= CAL1_CALC_IDEL;
- else begin
- // found second edge, record the current edge count
- if (cal1_first_edge_done && cal1_detect_edge) begin
- cal1_state <= CAL1_CALC_IDEL;
- cal1_found_second_edge <= 1'b1;
- cal1_bit_time_tap_cnt <= cal1_idel_tap_cnt -
- cal1_first_edge_tap_cnt + 1;
- end else begin
- cal1_state <= CAL1_SECOND_EDGE_IDEL_WAIT;
- cal1_data_chk_last <= cal1_data_chk_r;
- cal1_data_chk_last_valid <= 1'b1;
- cal1_dlyce_dq <= 1'b1;
- cal1_dlyinc_dq <= 1'b1;
- end
- end
- end
-
- // wait for DQ IDELAY to settle, then store ISERDES output
- CAL1_SECOND_EDGE_IDEL_WAIT:
- if (!idel_set_wait)
- cal1_state <= CAL1_FIND_SECOND_EDGE;
-
- // pipeline delay state to calculate amount to decrement DQ IDELAY
- // NOTE: We're calculating the amount to decrement by, not the
- // absolute setting for DQ IDELAY
- CAL1_CALC_IDEL: begin
- // if two edges found
- if (cal1_found_second_edge)
- // case 1: DQS was in DQ window to start with. First edge found
- // corresponds to left edge of DQ rising window. Backup by 1.5*BT
- // NOTE: In this particular case, it is possible to decrement
- // "below 0" in the case where DQS delay is less than 0.5*BT,
- // need to limit decrement to prevent IDELAY tap underflow
- if (!cal1_dqs_dq_init_phase)
- cal1_idel_dec_cnt <= {1'b0, cal1_bit_time_tap_cnt} +
- {1'b0, (cal1_bit_time_tap_cnt >> 1)};
- // case 2: DQS was in wrong DQ window (in DQ falling window).
- // First edge found is right edge of DQ rising window. Second
- // edge is left edge of DQ rising window. Backup by 0.5*BT
- else
- cal1_idel_dec_cnt <= {1'b0, (cal1_bit_time_tap_cnt >> 1)};
- // if only one edge found - assume will always be case 1 - DQS in
- // DQS window. Case 2 only possible if path delay on DQS > 5ns
- else
- cal1_idel_dec_cnt <= cal1_low_freq_idel_dec;
- cal1_state <= CAL1_DEC_IDEL;
- end
-
- // decrement DQ IDELAY for final adjustment
- CAL1_DEC_IDEL:
- // once adjustment is complete, we're done with calibration for
- // this DQ, now return to IDLE state and repeat for next DQ
- // Add underflow protection for case of 2 edges found and DQS
- // starting in DQ window (see comments for above state) - note we
- // have to take into account delayed value of CAL1_IDEL_TAP_CNT -
- // gets updated one clock cycle after CAL1_DLYCE/INC_DQ
- if ((cal1_idel_dec_cnt == 7'b0000000) ||
- (cal1_dlyce_dq && (cal1_idel_tap_cnt == 6'b000001))) begin
- cal1_state <= CAL1_DONE;
- // stop when all DQ's calibrated, or DQ[0] cal'ed (for sim)
- if ((count_dq == DQ_WIDTH-1) || (SIM_ONLY != 0))
- calib_done_tmp[0] <= 1'b1;
- else
- // need for VHDL simulation to prevent out-of-index error
- next_count_dq <= count_dq + 1;
- end else begin
- // keep decrementing until final tap count reached
- cal1_idel_dec_cnt <= cal1_idel_dec_cnt - 1;
- cal1_dlyce_dq <= 1'b1;
- cal1_dlyinc_dq <= 1'b0;
- end
-
- // delay state to allow count_dq and DATA_CHK to point to the next
- // DQ bit (allows us to potentially begin checking for an edge on
- // next DQ right away).
- CAL1_DONE:
- if (!idel_set_wait) begin
- count_dq <= next_count_dq;
- if (calib_done_tmp[0]) begin
- calib_done[0] <= 1'b1;
- cal1_state <= CAL1_IDLE;
- end else begin
- // request auto-refresh after every 8-bits calibrated to
- // avoid tRAS violation
- if (cal1_refresh) begin
- cal1_ref_req <= 1'b1;
- if (calib_ref_done)
- cal1_state <= CAL1_INIT;
- end else
- // if no need this time for refresh, proceed to next bit
- cal1_state <= CAL1_INIT;
- end
- end
- endcase
- end
-
- //***************************************************************************
- // Second stage calibration: DQS-FPGA Clock
- // Algorithm Description:
- // 1. Assumes a training pattern that will produce a pattern oscillating at
- // half the core clock frequency each on rise and fall outputs, and such
- // that rise and fall outputs are 180 degrees out of phase from each
- // other. Note that since the calibration logic runs at half the speed
- // of the interface, expect that data sampled with the slow clock always
- // to be constant (either always = 1, or = 0, and rise data != fall data)
- // unless we cross the edge of the data valid window
- // 2. Start by setting RD_DATA_SEL = 0. This selects the rising capture data
- // sync'ed to rising edge of core clock, and falling edge data sync'ed
- // to falling edge of core clock
- // 3. Start looking for an edge. An edge is defined as either: (1) a
- // change in capture value or (2) an invalid capture value (e.g. rising
- // data != falling data for that same clock cycle).
- // 4. If an edge is found, go to step (6). If edge hasn't been found, then
- // set RD_DATA_SEL = 1, and try again.
- // 5. If no edge is found, then increment IDELAY and return to step (3)
- // 6. If an edge if found, then invert RD_DATA_SEL - this shifts the
- // capture point 180 degrees from the edge of the window (minus duty
- // cycle distortion, delay skew between rising/falling edge capture
- // paths, etc.)
- // 7. If no edge is found by CAL2_IDEL_TAP_LIMIT (= 63 - # taps used for
- // stage 1 calibration), then decrement IDELAY (without reinverting
- // RD_DATA_SEL) by CAL2_IDEL_TAP_LIMIT/2. This guarantees we at least
- // have CAL2_IDEL_TAP_LIMIT/2 of slack both before and after the
- // capture point (not optimal, but best we can do not having found an
- // of the window). This happens only for very low frequencies.
- // 8. Repeat for each DQS group.
- // NOTE: Step 6 is not optimal. A better (and perhaps more complicated)
- // algorithm might be to find both edges of the data valid window (using
- // the same polarity of RD_DATA_SEL), and then decrement to the midpoint.
- //***************************************************************************
-
- // RD_DATA_SEL should be tagged with FROM-TO (multi-cycle) constraint in
- // UCF file to relax timing. This net is "pseudo-static" (after value is
- // changed, FSM waits number of cycles before using the output).
- // Note that we are adding one clock cycle of delay (to isolate it from
- // the other logic CAL2_RD_DATA_SEL feeds), make sure FSM waits long
- // enough to compensate (by default it does, it waits a few cycles more
- // than minimum # of clock cycles)
- genvar rd_i;
- generate
- for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rd_data_sel
- FDRSE u_ff_rd_data_sel
- (
- .Q (rd_data_sel[rd_i]),
- .C (clkdiv),
- .CE (1'b1),
- .D (cal2_rd_data_sel[rd_i]),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- end
- endgenerate
-
- //*****************************************************************
- // Max number of taps used for stg2 cal dependent on number of taps
- // used for stg1 (give priority to stg1 cal - let it use as many
- // taps as it needs - the remainder of the IDELAY taps can be used
- // by stg2)
- //*****************************************************************
-
- always @(posedge clkdiv)
- cal2_idel_tap_limit <= 6'b111111 - cal1_idel_max_tap;
-
- //*****************************************************************
- // second stage calibration uses readback pattern of "1100" (i.e.
- // 1st rising = 1, 1st falling = 1, 2nd rising = 0, 2nd falling = 0)
- // only look at the first bit of each DQS group
- //*****************************************************************
-
- // deasserted when captured data has changed since IDELAY was
- // incremented, or when we're right on the edge (i.e. rise data =
- // fall data).
- assign cal2_detect_edge =
- ((((rdd_rise_q1 != cal2_rd_data_rise_last_pos) ||
- (rdd_fall_q1 != cal2_rd_data_fall_last_pos)) &&
- cal2_rd_data_last_valid_pos && (!cal2_curr_sel)) ||
- (((rdd_rise_q1 != cal2_rd_data_rise_last_neg) ||
- (rdd_fall_q1 != cal2_rd_data_fall_last_neg)) &&
- cal2_rd_data_last_valid_neg && (cal2_curr_sel)) ||
- (rdd_rise_q1 != rdd_fall_q1));
-
- //*****************************************************************
- // keep track of edge tap counts found, and whether we've
- // incremented to the maximum number of taps allowed
- // NOTE: Assume stage 2 cal always increments the tap count (never
- // decrements) when searching for edge of the data valid window
- //*****************************************************************
-
- always @(posedge clkdiv)
- if (cal2_state == CAL2_INIT) begin
- cal2_idel_tap_limit_hit <= 1'b0;
- cal2_idel_tap_cnt <= 6'b000000;
- end else if (cal2_dlyce_dqs) begin
- cal2_idel_tap_cnt <= cal2_idel_tap_cnt + 1;
- cal2_idel_tap_limit_hit <= (cal2_idel_tap_cnt ==
- cal2_idel_tap_limit - 1);
- end
-
- //*****************************************************************
-
- always @(posedge clkdiv)
- if (rstdiv) begin
- calib_done[1] <= 1'b0;
- calib_done_tmp[1] <= 1'bx;
- calib_err[1] <= 1'b0;
- count_dqs <= 'b0;
- next_count_dqs <= 'b0;
- cal2_dlyce_dqs <= 1'b0;
- cal2_dlyinc_dqs <= 1'b0;
- cal2_idel_dec_cnt <= 6'bxxxxxx;
- cal2_rd_data_last_valid_neg <= 1'bx;
- cal2_rd_data_last_valid_pos <= 1'bx;
- cal2_rd_data_sel <= 'b0;
- cal2_ref_req <= 1'b0;
- cal2_state <= CAL2_IDLE;
- end else begin
- cal2_ref_req <= 1'b0;
- cal2_dlyce_dqs <= 1'b0;
- cal2_dlyinc_dqs <= 1'b0;
-
- case (cal2_state)
- CAL2_IDLE: begin
- count_dqs <= 'b0;
- next_count_dqs <= 'b0;
- if (calib_start[1]) begin
- cal2_rd_data_sel <= {DQS_WIDTH{1'b0}};
- calib_done[1] <= 1'b0;
- calib_done_tmp[1] <= 1'b0;
- cal2_state <= CAL2_INIT;
- end
- end
-
- // Pass through this state every time we calibrate a new DQS group
- CAL2_INIT: begin
- cal2_curr_sel <= 1'b0;
- cal2_rd_data_last_valid_neg <= 1'b0;
- cal2_rd_data_last_valid_pos <= 1'b0;
- cal2_state <= CAL2_INIT_IDEL_WAIT;
- end
-
- // Stall state only used if calibration run more than once. Can take
- // this state out if design never runs calibration more than once.
- // We need this state to give time for MUX'ed data to settle after
- // resetting RD_DATA_SEL
- CAL2_INIT_IDEL_WAIT:
- if (!idel_set_wait)
- cal2_state <= CAL2_FIND_EDGE_POS;
-
- // Look for an edge - first check "positive-edge" stage 2 capture
- CAL2_FIND_EDGE_POS: begin
- // if found an edge, then switch to the opposite edge stage 2
- // capture and we're done - no need to decrement the tap count,
- // since switching to the opposite edge will shift the capture
- // point by 180 degrees
- if (cal2_detect_edge) begin
- cal2_curr_sel <= 1'b1;
- cal2_state <= CAL2_DONE;
- // set all DQS groups to be the same for simulation
- if (SIM_ONLY != 0)
- cal2_rd_data_sel <= {DQS_WIDTH{1'b1}};
- else
- cal2_rd_data_sel[count_dqs] <= 1'b1;
- if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
- calib_done_tmp[1] <= 1'b1;
- else
- // MIG 2.1: Fix for simulation out-of-bounds error when
- // SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
- next_count_dqs <= count_dqs + 1;
- end else begin
- // otherwise, invert polarity of stage 2 capture and look for
- // an edge with opposite capture clock polarity
- cal2_curr_sel <= 1'b1;
- cal2_rd_data_sel[count_dqs] <= 1'b1;
- cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_POS;
- cal2_rd_data_rise_last_pos <= rdd_rise_q1;
- cal2_rd_data_fall_last_pos <= rdd_fall_q1;
- cal2_rd_data_last_valid_pos <= 1'b1;
- end
- end
-
- // Give time to switch from positive-edge to negative-edge second
- // stage capture (need time for data to filter though pipe stages)
- CAL2_FIND_EDGE_IDEL_WAIT_POS:
- if (!idel_set_wait)
- cal2_state <= CAL2_FIND_EDGE_NEG;
-
- // Look for an edge - check "negative-edge" stage 2 capture
- CAL2_FIND_EDGE_NEG:
- if (cal2_detect_edge) begin
- cal2_curr_sel <= 1'b0;
- cal2_state <= CAL2_DONE;
- // set all DQS groups to be the same for simulation
- if (SIM_ONLY != 0)
- cal2_rd_data_sel <= {DQS_WIDTH{1'b0}};
- else
- cal2_rd_data_sel[count_dqs] <= 1'b0;
- if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
- calib_done_tmp[1] <= 1'b1;
- else
- // MIG 2.1: Fix for simulation out-of-bounds error when
- // SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
- next_count_dqs <= count_dqs + 1;
- end else if (cal2_idel_tap_limit_hit) begin
- // otherwise, if we've run out of taps, then immediately
- // backoff by half # of taps used - that's our best estimate
- // for optimal calibration point. Doesn't matter whether which
- // polarity we're using for capture (we don't know which one is
- // best to use)
- cal2_idel_dec_cnt <= {1'b0, cal2_idel_tap_limit[5:1]};
- cal2_state <= CAL2_DEC_IDEL;
- if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
- calib_done_tmp[1] <= 1'b1;
- else
- // MIG 2.1: Fix for simulation out-of-bounds error when
- // SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
- next_count_dqs <= count_dqs + 1;
- end else begin
- // otherwise, increment IDELAY, and start looking for edge again
- cal2_curr_sel <= 1'b0;
- cal2_rd_data_sel[count_dqs] <= 1'b0;
- cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_NEG;
- cal2_rd_data_rise_last_neg <= rdd_rise_q1;
- cal2_rd_data_fall_last_neg <= rdd_fall_q1;
- cal2_rd_data_last_valid_neg <= 1'b1;
- cal2_dlyce_dqs <= 1'b1;
- cal2_dlyinc_dqs <= 1'b1;
- end
-
- CAL2_FIND_EDGE_IDEL_WAIT_NEG:
- if (!idel_set_wait)
- cal2_state <= CAL2_FIND_EDGE_POS;
-
- // if no edge found, then decrement by half # of taps used
- CAL2_DEC_IDEL: begin
- if (cal2_idel_dec_cnt == 6'b000000)
- cal2_state <= CAL2_DONE;
- else begin
- cal2_idel_dec_cnt <= cal2_idel_dec_cnt - 1;
- cal2_dlyce_dqs <= 1'b1;
- cal2_dlyinc_dqs <= 1'b0;
- end
- end
-
- // delay state to allow count_dqs and ISERDES data to point to next
- // DQ bit (DQS group) before going to INIT
- CAL2_DONE:
- if (!idel_set_wait) begin
- count_dqs <= next_count_dqs;
- if (calib_done_tmp[1]) begin
- calib_done[1] <= 1'b1;
- cal2_state <= CAL2_IDLE;
- end else begin
- // request auto-refresh after every DQS group calibrated to
- // avoid tRAS violation
- cal2_ref_req <= 1'b1;
- if (calib_ref_done)
- cal2_state <= CAL2_INIT;
- end
- end
- endcase
- end
-
- //***************************************************************************
- // Stage 3 calibration: Read Enable
- // Description:
- // read enable calibration determines the "round-trip" time (in # of CLK0
- // cycles) between when a read command is issued by the controller, and
- // when the corresponding read data is synchronized by into the CLK0 domain
- // this is a long delay chain to delay read enable signal from controller/
- // initialization logic (i.e. this is used for both initialization and
- // during normal controller operation). Stage 3 calibration logic decides
- // which delayed version is appropriate to use (which is affected by the
- // round trip delay of DQ/DQS) as a "valid" signal to tell rest of logic
- // when the captured data output from ISERDES is valid.
- //***************************************************************************
-
- //*****************************************************************
- // Delay chains: Use shift registers
- // Two sets of delay chains are used:
- // 1. One to delay RDEN from PHY_INIT module for calibration
- // purposes (delay required for RDEN for calibration is different
- // than during normal operation)
- // 2. One per DQS group to delay RDEN from controller for normal
- // operation - the value to delay for each DQS group can be different
- // as is determined during calibration
- //*****************************************************************
-
- //*****************************************************************
- // First delay chain, use only for calibration
- // input = asserted on rising edge of RDEN from PHY_INIT module
- //*****************************************************************
-
- always @(posedge clk) begin
- ctrl_rden_r <= ctrl_rden;
- phy_init_rden_r <= phy_init_rden;
- phy_init_rden_r1 <= phy_init_rden_r;
- calib_rden_edge_r <= phy_init_rden_r & ~phy_init_rden_r1;
- end
-
- // Calibration shift register used for both Stage 3 and Stage 4 cal
- // (not strictly necessary for stage 4, but use as an additional check
- // to make sure we're checking for correct data on the right clock cycle)
- always @(posedge clkdiv)
- if (!calib_done[2])
- calib_rden_srl_a <= cal3_rden_srl_a;
- else
- calib_rden_srl_a <= cal4_rden_srl_a;
-
- // Flops for targetting of multi-cycle path in UCF
- genvar cal_rden_ff_i;
- generate
- for (cal_rden_ff_i = 0; cal_rden_ff_i < 5;
- cal_rden_ff_i = cal_rden_ff_i+1) begin: gen_cal_rden_dly
- FDRSE u_ff_cal_rden_dly
- (
- .Q (calib_rden_srl_a_r[cal_rden_ff_i]),
- .C (clkdiv),
- .CE (1'b1),
- .D (calib_rden_srl_a[cal_rden_ff_i]),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- end
- endgenerate
-
- SRLC32E u_calib_rden_srl
- (
- .Q (calib_rden_srl_out),
- .Q31 (),
- .A (calib_rden_srl_a_r),
- .CE (1'b1),
- .CLK (clk),
- .D (calib_rden_edge_r)
- );
-
- FDRSE u_calib_rden_srl_out_r
- (
- .Q (calib_rden_srl_out_r),
- .C (clk),
- .CE (1'b1),
- .D (calib_rden_srl_out),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve = 1 */;
-
- // convert to CLKDIV domain. Two version are generated because we need
- // to be able to tell exactly which fast (clk) clock cycle the read
- // enable was asserted in. Only one of CALIB_DATA_VALID or
- // CALIB_DATA_VALID_STGD will be asserted for any given shift value
- always @(posedge clk)
- calib_rden_srl_out_r1 <= calib_rden_srl_out_r;
-
- always @(posedge clkdiv) begin
- calib_rden_valid <= calib_rden_srl_out_r;
- calib_rden_valid_stgd <= calib_rden_srl_out_r1;
- end
-
- //*****************************************************************
- // Second set of delays chain, use for normal reads
- // input = RDEN from controller
- //*****************************************************************
-
- // Flops for targetting of multi-cycle path in UCF
- genvar rden_ff_i;
- generate
- for (rden_ff_i = 0; rden_ff_i < 5*DQS_WIDTH;
- rden_ff_i = rden_ff_i+1) begin: gen_rden_dly
- FDRSE u_ff_rden_dly
- (
- .Q (rden_dly_r[rden_ff_i]),
- .C (clkdiv),
- .CE (1'b1),
- .D (rden_dly[rden_ff_i]),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- end
- endgenerate
-
- // NOTE: Comment this section explaining purpose of SRL's
- genvar rden_i;
- generate
- for (rden_i = 0; rden_i < DQS_WIDTH; rden_i = rden_i + 1) begin: gen_rden
- SRLC32E u_rden_srl
- (
- .Q (rden_srl_out[rden_i]),
- .Q31 (),
- .A ({rden_dly_r[(rden_i*5)+4],
- rden_dly_r[(rden_i*5)+3],
- rden_dly_r[(rden_i*5)+2],
- rden_dly_r[(rden_i*5)+1],
- rden_dly_r[(rden_i*5)]}),
- .CE (1'b1),
- .CLK (clk),
- .D (ctrl_rden_r)
- );
- FDRSE u_calib_rden_r
- (
- .Q (calib_rden[rden_i]),
- .C (clk),
- .CE (1'b1),
- .D (rden_srl_out[rden_i]),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve = 1 */;
- end
- endgenerate
-
- //*****************************************************************
- // indicates that current received data is the correct pattern. Check both
- // rising and falling data for first DQ in each DQS group. Note that
- // we're checking using a pipelined version of read data, so need to take
- // this inherent delay into account in determining final read valid delay
- // Data is written to the memory in the following order (first -> last):
- // 0x1, 0xE, 0xE, 0x1, 0x1, 0xE, 0x1, 0xE
- // Looking at the two LSb bits, expect data in sequence (in binary):
- // bit[0]: 1, 0, 0, 1, 0, 1, 0, 1
- // bit[1]: 0, 1, 1, 0, 1, 0, 1, 0
- // Check for the presence of the first 7 words, and compensate read valid
- // delay accordingly. Don't check last falling edge data, it may be
- // corrupted by the DQS tri-state glitch at end of read postamble
- // (glitch protection not yet active until stage 4 cal)
- //*****************************************************************
-
- always @(posedge clkdiv) begin
- rdd_rise_q1_r <= rdd_rise_q1;
- rdd_fall_q1_r <= rdd_fall_q1;
- rdd_rise_q2_r <= rdd_rise_q2;
- rdd_fall_q2_r <= rdd_fall_q2;
- rdd_rise_q1_r1 <= rdd_rise_q1_r;
- rdd_fall_q1_r1 <= rdd_fall_q1_r;
- // MIG 3.3: Added comparison for second bit in DQS group for stage 3 cal
- rdd_rise_q1_bit1_r <= rdd_rise_q1_bit1;
- rdd_fall_q1_bit1_r <= rdd_fall_q1_bit1;
- rdd_rise_q2_bit1_r <= rdd_rise_q2_bit1;
- rdd_fall_q2_bit1_r <= rdd_fall_q2_bit1;
- rdd_rise_q1_bit1_r1 <= rdd_rise_q1_bit1_r;
- rdd_fall_q1_bit1_r1 <= rdd_fall_q1_bit1_r;
- end
-
- always @(posedge clkdiv) begin
- // For the following sequence from memory:
- // rise[0], fall[0], rise[1], fall[1]
- // if data is aligned out of fabric ISERDES:
- // RDD_RISE_Q2 = rise[0]
- // RDD_FALL_Q2 = fall[0]
- // RDD_RISE_Q1 = rise[1]
- // RDD_FALL_Q1 = fall[1]
- cal3_data_match <= ((rdd_rise_q2_r == 1) &&
- (rdd_fall_q2_r == 0) &&
- (rdd_rise_q1_r == 0) &&
- (rdd_fall_q1_r == 1) &&
- (rdd_rise_q2 == 0) &&
- (rdd_fall_q2 == 1) &&
- (rdd_rise_q1 == 0) &&
- (rdd_rise_q2_bit1_r == 0) &&
- (rdd_fall_q2_bit1_r == 1) &&
- (rdd_rise_q1_bit1_r == 1) &&
- (rdd_fall_q1_bit1_r == 0) &&
- (rdd_rise_q2_bit1 == 1) &&
- (rdd_fall_q2_bit1 == 0) &&
- (rdd_rise_q1_bit1 == 1));
-
- // if data is staggered out of fabric ISERDES:
- // RDD_RISE_Q1_R = rise[0]
- // RDD_FALL_Q1_R = fall[0]
- // RDD_RISE_Q2 = rise[1]
- // RDD_FALL_Q2 = fall[1]
- cal3_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
- (rdd_fall_q1_r1 == 0) &&
- (rdd_rise_q2_r == 0) &&
- (rdd_fall_q2_r == 1) &&
- (rdd_rise_q1_r == 0) &&
- (rdd_fall_q1_r == 1) &&
- (rdd_rise_q2 == 0) &&
- (rdd_rise_q1_bit1_r1 == 0) &&
- (rdd_fall_q1_bit1_r1 == 1) &&
- (rdd_rise_q2_bit1_r == 1) &&
- (rdd_fall_q2_bit1_r == 0) &&
- (rdd_rise_q1_bit1_r == 1) &&
- (rdd_fall_q1_bit1_r == 0) &&
- (rdd_rise_q2_bit1 == 1));
- end
-
- assign cal3_rden_dly = cal3_rden_srl_a - CAL3_RDEN_SRL_DLY_DELTA;
- assign cal3_data_valid = (calib_rden_valid | calib_rden_valid_stgd);
- assign cal3_match_found
- = ((calib_rden_valid && cal3_data_match) ||
- (calib_rden_valid_stgd && cal3_data_match_stgd));
-
- // when calibrating, check to see which clock cycle (after the read is
- // issued) does the expected data pattern arrive. Record this result
- // NOTE: Can add error checking here in case valid data not found on any
- // of the available pipeline stages
- always @(posedge clkdiv) begin
- if (rstdiv) begin
- cal3_rden_srl_a <= 5'bxxxxx;
- cal3_state <= CAL3_IDLE;
- calib_done[2] <= 1'b0;
- calib_err_2[0] <= 1'b0;
- count_rden <= {DQS_WIDTH{1'b0}};
- rden_dly <= {5*DQS_WIDTH{1'b0}};
- end else begin
-
- case (cal3_state)
- CAL3_IDLE: begin
- count_rden <= {DQS_WIDTH{1'b0}};
- if (calib_start[2]) begin
- calib_done[2] <= 1'b0;
- cal3_state <= CAL3_INIT;
- end
- end
-
- CAL3_INIT: begin
- cal3_rden_srl_a <= RDEN_BASE_DELAY;
- // let SRL pipe clear after loading initial shift value
- cal3_state <= CAL3_RDEN_PIPE_CLR_WAIT;
- end
-
- CAL3_DETECT:
- if (cal3_data_valid)
- // if match found at the correct clock cycle
- if (cal3_match_found) begin
-
- // For simulation, load SRL addresses for all DQS with same value
- if (SIM_ONLY != 0) begin
- for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_rden_dly
- rden_dly[(i*5)] <= cal3_rden_dly[0];
- rden_dly[(i*5)+1] <= cal3_rden_dly[1];
- rden_dly[(i*5)+2] <= cal3_rden_dly[2];
- rden_dly[(i*5)+3] <= cal3_rden_dly[3];
- rden_dly[(i*5)+4] <= cal3_rden_dly[4];
- end
- end else begin
- rden_dly[(count_rden*5)] <= cal3_rden_dly[0];
- rden_dly[(count_rden*5)+1] <= cal3_rden_dly[1];
- rden_dly[(count_rden*5)+2] <= cal3_rden_dly[2];
- rden_dly[(count_rden*5)+3] <= cal3_rden_dly[3];
- rden_dly[(count_rden*5)+4] <= cal3_rden_dly[4];
- end
-
- // Use for stage 4 calibration
- calib_rden_dly[(count_rden*5)] <= cal3_rden_srl_a[0];
- calib_rden_dly[(count_rden*5)+1] <= cal3_rden_srl_a[1];
- calib_rden_dly[(count_rden*5)+2] <= cal3_rden_srl_a[2];
- calib_rden_dly[(count_rden*5)+3] <= cal3_rden_srl_a[3];
- calib_rden_dly[(count_rden*5)+4] <= cal3_rden_srl_a[4];
- cal3_state <= CAL3_DONE;
- end else begin
- // If we run out of stages to shift, without finding correct
- // result, the stop and assert error
- if (cal3_rden_srl_a == 5'b11111) begin
- calib_err_2[0] <= 1'b1;
- cal3_state <= CAL3_IDLE;
- end else begin
- // otherwise, increase the shift value and try again
- cal3_rden_srl_a <= cal3_rden_srl_a + 1;
- cal3_state <= CAL3_RDEN_PIPE_CLR_WAIT;
- end
- end
-
- // give additional time for RDEN_R pipe to clear from effects of
- // previous pipeline or IDELAY tap change
- CAL3_RDEN_PIPE_CLR_WAIT:
- if (calib_rden_pipe_cnt == 5'b00000)
- cal3_state <= CAL3_DETECT;
-
- CAL3_DONE: begin
- if ((count_rden == DQS_WIDTH-1) || (SIM_ONLY != 0)) begin
- calib_done[2] <= 1'b1;
- cal3_state <= CAL3_IDLE;
- end else begin
- count_rden <= count_rden + 1;
- cal3_state <= CAL3_INIT;
- end
- end
- endcase
- end
- end
-
- //*****************************************************************
- // Last part of stage 3 calibration - compensate for differences
- // in delay between different DQS groups. Assume that in the worst
- // case, DQS groups can only differ by one clock cycle. Data for
- // certain DQS groups must be delayed by one clock cycle.
- // NOTE: May need to increase allowable variation to greater than
- // one clock cycle in certain customer designs.
- // Algorithm is:
- // 1. Record shift delay value for DQS[0]
- // 2. Compare each DQS[x] delay value to that of DQS[0]:
- // - If different, than record this fact (RDEN_MUX)
- // - If greater than DQS[0], set RDEN_INC. Assume greater by
- // one clock cycle only - this is a key assumption, assume no
- // more than a one clock cycle variation.
- // - If less than DQS[0], set RDEN_DEC
- // 3. After calibration is complete, set control for DQS group
- // delay (CALIB_RDEN_SEL):
- // - If RDEN_DEC = 1, then assume that DQS[0] is the lowest
- // delay (and at least one other DQS group has a higher
- // delay).
- // - If RDEN_INC = 1, then assume that DQS[0] is the highest
- // delay (and that all other DQS groups have the same or
- // lower delay).
- // - If both RDEN_INC and RDEN_DEC = 1, then flag error
- // (variation is too high for this algorithm to handle)
- //*****************************************************************
-
- always @(posedge clkdiv) begin
- if (rstdiv) begin
- calib_err_2[1] <= 1'b0;
- calib_rden_sel <= {DQS_WIDTH{1'bx}};
- rden_dec <= 1'b0;
- rden_dly_0 <= 5'bxxxxx;
- rden_inc <= 1'b0;
- rden_mux <= {DQS_WIDTH{1'b0}};
- end else begin
- // if a match if found, then store the value of rden_dly
- if (!calib_done[2]) begin
- if ((cal3_state == CAL3_DETECT) && cal3_match_found) begin
- // store the value for DQS[0] as a reference
- if (count_rden == 0) begin
- // for simulation, RDEN calibration only happens for DQS[0]
- // set RDEN_MUX for all DQS groups to be the same as DQS[0]
- if (SIM_ONLY != 0)
- rden_mux <= {DQS_WIDTH{1'b0}};
- else begin
- // otherwise, load values for DQS[0]
- rden_dly_0 <= cal3_rden_srl_a;
- rden_mux[0] <= 1'b0;
- end
- end else if (SIM_ONLY == 0) begin
- // for all other DQS groups, compare RDEN_DLY delay value with
- // that of DQS[0]
- if (rden_dly_0 != cal3_rden_srl_a) begin
- // record that current DQS group has a different delay
- // than DQS[0] (the "reference" DQS group)
- rden_mux[count_rden] <= 1'b1;
- if (rden_dly_0 > cal3_rden_srl_a)
- rden_inc <= 1'b1;
- else if (rden_dly_0 < cal3_rden_srl_a)
- rden_dec <= 1'b1;
- // otherwise, if current DQS group has same delay as DQS[0],
- // then rden_mux[count_rden] remains at 0 (since rden_mux
- // array contents initialized to 0)
- end
- end
- end
- end else begin
- // Otherwise - if we're done w/ stage 2 calibration:
- // set final value for RDEN data delay
- // flag error if there's more than one cycle variation from DQS[0]
- calib_err_2[1] <= (rden_inc && rden_dec);
- if (rden_inc)
- // if DQS[0] delay represents max delay
- calib_rden_sel <= ~rden_mux;
- else
- // if DQS[0] delay represents min delay (or all the delays are
- // the same between DQS groups)
- calib_rden_sel <= rden_mux;
- end
- end
- end
-
- // flag error for stage 3 if appropriate
- always @(posedge clkdiv)
- calib_err[2] <= calib_err_2[0] | calib_err_2[1];
-
- //***************************************************************************
- // Stage 4 calibration: DQS gate
- //***************************************************************************
-
- //*****************************************************************
- // indicates that current received data is the correct pattern. Same as
- // for READ VALID calibration, except that the expected data sequence is
- // different since DQS gate is asserted after the 6th word.
- // Data sequence:
- // Arrives from memory (at FPGA input) (R, F): 1 0 0 1 1 0 0 1
- // After gating the sequence looks like: 1 0 0 1 1 0 1 0 (7th word =
- // 5th word, 8th word = 6th word)
- // What is the gate timing is off? Need to make sure we can distinquish
- // between the results of correct vs. incorrect gate timing. We also use
- // the "read_valid" signal from stage 3 calibration to help us determine
- // when to check for a valid sequence for stage 4 calibration (i.e. use
- // CAL4_DATA_VALID in addition to CAL4_DATA_MATCH/CAL4_DATA_MATCH_STGD)
- // Note that since the gate signal from the CLK0 domain is synchronized
- // to the falling edge of DQS, that the effect of the gate will only be
- // seen starting with a rising edge data (although it is possible
- // the GATE IDDR output could go metastable and cause a unexpected result
- // on the first rising and falling edges after the gate is enabled).
- // Also note that the actual DQS glitch can come more than 0.5*tCK after
- // the last falling edge of DQS and the constraint for this path is can
- // be > 0.5*tCK; however, this means when calibrating, the output of the
- // GATE IDDR may miss the setup time requirement of the rising edge flop
- // and only meet it for the falling edge flop. Therefore the rising
- // edge data immediately following the assertion of the gate can either
- // be a 1 or 0 (can rely on either)
- // As the timing on the gate is varied, we expect to see (sequence of
- // captured read data shown below):
- // - 1 0 0 1 1 0 0 1 (gate is really early, starts and ends before
- // read burst even starts)
- // - x 0 0 1 1 0 0 1 (gate pulse starts before the burst, and ends
- // - x y 0 1 1 0 0 1 sometime during the burst; x,y = 0, or 1, but
- // - x y x 1 1 0 0 1 all bits that show an x are the same value,
- // - x y x y 1 0 0 1 and y are the same value)
- // - x y x y x 0 0 1
- // - x y x y x y 0 1 (gate starts just before start of burst)
- // - 1 0 x 0 x 0 x 0 (gate starts after 1st falling word. The "x"
- // represents possiblity that gate may not disable
- // clock for 2nd rising word in time)
- // - 1 0 0 1 x 1 x 1 (gate starts after 2nd falling word)
- // - 1 0 0 1 1 0 x 0 (gate starts after 3rd falling word - GOOD!!)
- // - 1 0 0 1 1 0 0 1 (gate starts after burst is already done)
- //*****************************************************************
-
- assign cal4_data_valid = calib_rden_valid | calib_rden_valid_stgd;
- assign cal4_data_good = (calib_rden_valid &
- cal4_data_match) |
- (calib_rden_valid_stgd &
- cal4_data_match_stgd);
-
- always @(posedge clkdiv) begin
- // if data is aligned out of fabric ISERDES:
- cal4_data_match <= ((rdd_rise_q2_r == 1) &&
- (rdd_fall_q2_r == 0) &&
- (rdd_rise_q1_r == 0) &&
- (rdd_fall_q1_r == 1) &&
- (rdd_rise_q2 == 1) &&
- (rdd_fall_q2 == 0) &&
- // MIG 2.1: Last rising edge data value not
- // guaranteed to be certain value at higher
- // frequencies
- // (rdd_rise_q1 == 0) &&
- (rdd_fall_q1 == 0));
- // if data is staggered out of fabric ISERDES:
- cal4_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
- (rdd_fall_q1_r1 == 0) &&
- (rdd_rise_q2_r == 0) &&
- (rdd_fall_q2_r == 1) &&
- (rdd_rise_q1_r == 1) &&
- (rdd_fall_q1_r == 0) &&
- // MIG 2.1: Last rising edge data value not
- // guaranteed to be certain value at higher
- // frequencies
- // (rdd_rise_q2 == 0) &&
- (rdd_fall_q2 == 0));
- end
-
- //*****************************************************************
- // DQS gate enable generation:
- // This signal gets synchronized to DQS domain, and drives IDDR
- // register that in turn asserts/deasserts CE to all 4 or 8 DQ
- // IDDR's in that DQS group.
- // 1. During normal (post-cal) operation, this is only for 2 clock
- // cycles following the end of a burst. Check for falling edge
- // of RDEN. But must also make sure NOT assert for a read-idle-
- // read (two non-consecutive reads, separated by exactly one
- // idle cycle) - in this case, don't assert the gate because:
- // (1) we don't have enough time to deassert the gate before the
- // first rising edge of DQS for second burst (b/c of fact
- // that DQS gate is generated in the fabric only off rising
- // edge of CLK0 - if we somehow had an ODDR in fabric, we
- // could pull this off, (2) assumption is that the DQS glitch
- // will not rise enough to cause a glitch because the
- // post-amble of the first burst is followed immediately by
- // the pre-amble of the next burst
- // 2. During stage 4 calibration, assert for 3 clock cycles
- // (assert gate enable one clock cycle early), since we gate out
- // the last two words (in addition to the crap on the DQ bus after
- // the DQS read postamble).
- // NOTE: PHY_INIT_RDEN and CTRL_RDEN have slightly different timing w/r
- // to when they are asserted w/r to the start of the read burst
- // (PHY_INIT_RDEN is one cycle earlier than CTRL_RDEN).
- //*****************************************************************
-
- // register for timing purposes for fast clock path - currently only
- // calib_done_r[2] used
- always @(posedge clk)
- calib_done_r <= calib_done;
-
- always @(*) begin
- calib_ctrl_rden = ctrl_rden;
- calib_init_rden = calib_done_r[2] & phy_init_rden;
- end
-
- assign calib_ctrl_rden_negedge = ~calib_ctrl_rden & calib_ctrl_rden_r;
- // check for read-idle-read before asserting DQS pulse at end of read
- assign calib_ctrl_gate_pulse = calib_ctrl_rden_negedge_r &
- ~calib_ctrl_rden;
- always @(posedge clk) begin
- calib_ctrl_rden_r <= calib_ctrl_rden;
- calib_ctrl_rden_negedge_r <= calib_ctrl_rden_negedge;
- calib_ctrl_gate_pulse_r <= calib_ctrl_gate_pulse;
- end
-
- assign calib_init_gate_pulse = ~calib_init_rden & calib_init_rden_r;
- always @(posedge clk) begin
- calib_init_rden_r <= calib_init_rden;
- calib_init_gate_pulse_r <= calib_init_gate_pulse;
- calib_init_gate_pulse_r1 <= calib_init_gate_pulse_r;
- end
-
- // Gate is asserted: (1) during cal, for 3 cycles, starting 1 cycle
- // after falling edge of CTRL_RDEN, (2) during normal ops, for 2
- // cycles, starting 2 cycles after falling edge of CTRL_RDEN
- assign gate_srl_in = ~((calib_ctrl_gate_pulse |
- calib_ctrl_gate_pulse_r) |
- (calib_init_gate_pulse |
- calib_init_gate_pulse_r |
- calib_init_gate_pulse_r1));
-
- //*****************************************************************
- // generate DQS enable signal for each DQS group
- // There are differences between DQS gate signal for calibration vs. during
- // normal operation:
- // * calibration gates the second to last clock cycle of the burst,
- // rather than after the last word (e.g. for a 8-word, 4-cycle burst,
- // cycle 4 is gated for calibration; during normal operation, cycle
- // 5 (i.e. cycle after the last word) is gated)
- // enable for DQS is deasserted for two clock cycles, except when
- // we have the preamble for the next read immediately following
- // the postamble of the current read - assume DQS does not glitch
- // during this time, that it stays low. Also if we did have to gate
- // the DQS for this case, then we don't have enough time to deassert
- // the gate in time for the first rising edge of DQS for the second
- // read
- //*****************************************************************
-
- // Flops for targetting of multi-cycle path in UCF
- genvar gate_ff_i;
- generate
- for (gate_ff_i = 0; gate_ff_i < 5*DQS_WIDTH;
- gate_ff_i = gate_ff_i+1) begin: gen_gate_dly
- FDRSE u_ff_gate_dly
- (
- .Q (gate_dly_r[gate_ff_i]),
- .C (clkdiv),
- .CE (1'b1),
- .D (gate_dly[gate_ff_i]),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- end
- endgenerate
-
- genvar gate_i;
- generate
- for (gate_i = 0; gate_i < DQS_WIDTH; gate_i = gate_i + 1) begin: gen_gate
- SRLC32E u_gate_srl
- (
- .Q (gate_srl_out[gate_i]),
- .Q31 (),
- .A ({gate_dly_r[(gate_i*5)+4],
- gate_dly_r[(gate_i*5)+3],
- gate_dly_r[(gate_i*5)+2],
- gate_dly_r[(gate_i*5)+1],
- gate_dly_r[(gate_i*5)]}),
- .CE (1'b1),
- .CLK (clk),
- .D (gate_srl_in)
- );
-
- // For GATE_BASE_DELAY > 0, have one extra cycle to register outputs
- // from controller before generating DQS gate pulse. In PAR, the
- // location of the controller logic can be far from the DQS gate
- // logic (DQS gate logic located near the DQS I/O's), contributing
- // to large net delays. Registering the controller outputs for
- // CL >= 4 (above 200MHz) adds a stage of pipelining to reduce net
- // delays
- if (GATE_BASE_DELAY > 0) begin: gen_gate_base_dly_gt3
- // add flop between SRL32 and EN_DQS flop (which is located near the
- // DDR2 IOB's)
- FDRSE u_gate_srl_ff
- (
- .Q (gate_srl_out_r[gate_i]),
- .C (clk),
- .CE (1'b1),
- .D (gate_srl_out[gate_i]),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve = 1 */;
- end else begin: gen_gate_base_dly_le3
- assign gate_srl_out_r[gate_i] = gate_srl_out[gate_i];
- end
-
- FDRSE u_en_dqs_ff
- (
- .Q (en_dqs[gate_i]),
- .C (clk),
- .CE (1'b1),
- .D (gate_srl_out_r[gate_i]),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve = 1 */
- /* synthesis syn_replicate = 0 */;
- end
- endgenerate
-
- //*****************************************************************
- // Find valid window: keep track of how long we've been in the same data
- // window. If it's been long enough, then declare that we've found a stable
- // valid window - in particular, that we're past any region of instability
- // associated with the edge of the window. Use only when finding left edge
- //*****************************************************************
-
- always @(posedge clkdiv)
- // reset before we start to look for window
- if (cal4_state == CAL4_INIT) begin
- cal4_window_cnt <= 4'b0000;
- cal4_stable_window <= 1'b0;
- end else if ((cal4_state == CAL4_FIND_EDGE) && cal4_seek_left) begin
- // if we're looking for left edge, and incrementing IDELAY, count
- // consecutive taps over which we're in the window
- if (cal4_data_valid) begin
- if (cal4_data_good)
- cal4_window_cnt <= cal4_window_cnt + 1;
- else
- cal4_window_cnt <= 4'b0000;
- end
-
- if (cal4_window_cnt == MIN_WIN_SIZE-1)
- cal4_stable_window <= 1'b1;
- end
-
- //*****************************************************************
- // keep track of edge tap counts found, and whether we've
- // incremented to the maximum number of taps allowed
- //*****************************************************************
-
- always @(posedge clkdiv)
- if ((cal4_state == CAL4_INIT) || cal4_dlyrst_gate) begin
- cal4_idel_max_tap <= 1'b0;
- cal4_idel_bit_tap <= 1'b0;
- cal4_idel_tap_cnt <= 6'b000000;
- end else if (cal4_dlyce_gate) begin
- if (cal4_dlyinc_gate) begin
- cal4_idel_tap_cnt <= cal4_idel_tap_cnt + 1;
- cal4_idel_bit_tap <= (cal4_idel_tap_cnt == CAL4_IDEL_BIT_VAL-2);
- cal4_idel_max_tap <= (cal4_idel_tap_cnt == 6'b111110);
- end else begin
- cal4_idel_tap_cnt <= cal4_idel_tap_cnt - 1;
- cal4_idel_bit_tap <= 1'b0;
- cal4_idel_max_tap <= 1'b0;
- end
- end
-
- always @(posedge clkdiv)
- if ((cal4_state != CAL4_RDEN_PIPE_CLR_WAIT) &&
- (cal3_state != CAL3_RDEN_PIPE_CLR_WAIT))
- calib_rden_pipe_cnt <= CALIB_RDEN_PIPE_LEN-1;
- else
- calib_rden_pipe_cnt <= calib_rden_pipe_cnt - 1;
-
- //*****************************************************************
- // Stage 4 cal state machine
- //*****************************************************************
-
- always @(posedge clkdiv)
- if (rstdiv) begin
- calib_done[3] <= 1'b0;
- calib_done_tmp[3] <= 1'b0;
- calib_err[3] <= 1'b0;
- count_gate <= 'b0;
- gate_dly <= 'b0;
- next_count_gate <= 'b0;
- cal4_idel_adj_cnt <= 6'bxxxxxx;
- cal4_dlyce_gate <= 1'b0;
- cal4_dlyinc_gate <= 1'b0;
- cal4_dlyrst_gate <= 1'b0; // reset handled elsewhere in code
- cal4_gate_srl_a <= 5'bxxxxx;
- cal4_rden_srl_a <= 5'bxxxxx;
- cal4_ref_req <= 1'b0;
- cal4_seek_left <= 1'bx;
- cal4_state <= CAL4_IDLE;
- end else begin
- cal4_ref_req <= 1'b0;
- cal4_dlyce_gate <= 1'b0;
- cal4_dlyinc_gate <= 1'b0;
- cal4_dlyrst_gate <= 1'b0;
-
- case (cal4_state)
- CAL4_IDLE: begin
- count_gate <= 'b0;
- next_count_gate <= 'b0;
- if (calib_start[3]) begin
- gate_dly <= 'b0;
- calib_done[3] <= 1'b0;
- cal4_state <= CAL4_INIT;
- end
- end
-
- CAL4_INIT: begin
- // load: (1) initial value of gate delay SRL, (2) appropriate
- // value of RDEN SRL (so that we get correct "data valid" timing)
- cal4_gate_srl_a <= GATE_BASE_INIT;
- cal4_rden_srl_a <= {calib_rden_dly[(count_gate*5)+4],
- calib_rden_dly[(count_gate*5)+3],
- calib_rden_dly[(count_gate*5)+2],
- calib_rden_dly[(count_gate*5)+1],
- calib_rden_dly[(count_gate*5)]};
- // let SRL pipe clear after loading initial shift value
- cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
- end
-
- // sort of an initial state - start checking to see whether we're
- // already in the window or not
- CAL4_FIND_WINDOW:
- // decide right away if we start in the proper window - this
- // determines if we are then looking for the left (trailing) or
- // right (leading) edge of the data valid window
- if (cal4_data_valid) begin
- // if we find a match - then we're already in window, now look
- // for left edge. Otherwise, look for right edge of window
- cal4_seek_left <= cal4_data_good;
- cal4_state <= CAL4_FIND_EDGE;
- end
-
- CAL4_FIND_EDGE:
- // don't do anything until the exact clock cycle when to check that
- // readback data is valid or not
- if (cal4_data_valid) begin
- // we're currently in the window, look for left edge of window
- if (cal4_seek_left) begin
- // make sure we've passed the right edge before trying to detect
- // the left edge (i.e. avoid any edge "instability") - else, we
- // may detect an "false" edge too soon. By design, if we start in
- // the data valid window, always expect at least
- // MIN(BIT_TIME_TAPS,32) (-/+ jitter, see below) taps of valid
- // window before we hit the left edge (this is because when stage
- // 4 calibration first begins (i.e., gate_dly = 00, and IDELAY =
- // 00), we're guaranteed to NOT be in the window, and we always
- // start searching for MIN(BIT_TIME_TAPS,32) for the right edge
- // of window. If we don't find it, increment gate_dly, and if we
- // now start in the window, we have at least approximately
- // CLK_PERIOD-MIN(BIT_TIME_TAPS,32) = MIN(BIT_TIME_TAPS,32) taps.
- // It's approximately because jitter, noise, etc. can bring this
- // value down slightly. Because of this (although VERY UNLIKELY),
- // we have to protect against not decrementing IDELAY below 0
- // during adjustment phase).
- if (cal4_stable_window && !cal4_data_good) begin
- // found left edge of window, dec by MIN(BIT_TIME_TAPS,32)
- cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
- cal4_idel_adj_inc <= 1'b0;
- cal4_state <= CAL4_ADJ_IDEL;
- end else begin
- // Otherwise, keep looking for left edge:
- if (cal4_idel_max_tap) begin
- // ran out of taps looking for left edge (max=63) - happens
- // for low frequency case, decrement by 32
- cal4_idel_adj_cnt <= 6'b100000;
- cal4_idel_adj_inc <= 1'b0;
- cal4_state <= CAL4_ADJ_IDEL;
- end else begin
- cal4_dlyce_gate <= 1'b1;
- cal4_dlyinc_gate <= 1'b1;
- cal4_state <= CAL4_IDEL_WAIT;
- end
- end
- end else begin
- // looking for right edge of window:
- // look for the first match - this means we've found the right
- // (leading) edge of the data valid window, increment by
- // MIN(BIT_TIME_TAPS,32)
- if (cal4_data_good) begin
- cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
- cal4_idel_adj_inc <= 1'b1;
- cal4_state <= CAL4_ADJ_IDEL;
- end else begin
- // Otherwise, keep looking:
- // only look for MIN(BIT_TIME_TAPS,32) taps for right edge,
- // if we haven't found it, then inc gate delay, try again
- if (cal4_idel_bit_tap) begin
- // if we're already maxed out on gate delay, then error out
- // (simulation only - calib_err isn't currently connected)
- if (cal4_gate_srl_a == 5'b11111) begin
- calib_err[3] <= 1'b1;
- cal4_state <= CAL4_IDLE;
- end else begin
- // otherwise, increment gate delay count, and start
- // over again
- cal4_gate_srl_a <= cal4_gate_srl_a + 1;
- cal4_dlyrst_gate <= 1'b1;
- cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
- end
- end else begin
- // keep looking for right edge
- cal4_dlyce_gate <= 1'b1;
- cal4_dlyinc_gate <= 1'b1;
- cal4_state <= CAL4_IDEL_WAIT;
- end
- end
- end
- end
-
- // wait for GATE IDELAY to settle, after reset or increment
- CAL4_IDEL_WAIT: begin
- // For simulation, load SRL addresses for all DQS with same value
- if (SIM_ONLY != 0) begin
- for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly
- gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
- gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
- gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
- gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
- gate_dly[(i*5)] <= cal4_gate_srl_a[0];
- end
- end else begin
- gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
- gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
- gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
- gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
- gate_dly[(count_gate*5)] <= cal4_gate_srl_a[0];
- end
- // check to see if we've found edge of window
- if (!idel_set_wait)
- cal4_state <= CAL4_FIND_EDGE;
- end
-
- // give additional time for RDEN_R pipe to clear from effects of
- // previous pipeline (and IDELAY reset)
- CAL4_RDEN_PIPE_CLR_WAIT: begin
- // MIG 2.2: Bug fix - make sure to update GATE_DLY count, since
- // possible for FIND_EDGE->RDEN_PIPE_CLR_WAIT->FIND_WINDOW
- // transition (i.e. need to make sure the gate count updated in
- // FIND_EDGE gets reflected in GATE_DLY by the time we reach
- // state FIND_WINDOW) - previously GATE_DLY only being updated
- // during state CAL4_IDEL_WAIT
- if (SIM_ONLY != 0) begin
- for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly_pipe
- gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
- gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
- gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
- gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
- gate_dly[(i*5)] <= cal4_gate_srl_a[0];
- end
- end else begin
- gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
- gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
- gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
- gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
- gate_dly[(count_gate*5)] <= cal4_gate_srl_a[0];
- end
- // look for new window
- if (calib_rden_pipe_cnt == 5'b00000)
- cal4_state <= CAL4_FIND_WINDOW;
- end
-
- // increment/decrement DQS/DQ IDELAY for final adjustment
- CAL4_ADJ_IDEL:
- // add underflow protection for corner case when left edge found
- // using fewer than MIN(BIT_TIME_TAPS,32) taps
- if ((cal4_idel_adj_cnt == 6'b000000) ||
- (cal4_dlyce_gate && !cal4_dlyinc_gate &&
- (cal4_idel_tap_cnt == 6'b000001))) begin
- cal4_state <= CAL4_DONE;
- // stop when all gates calibrated, or gate[0] cal'ed (for sim)
- if ((count_gate == DQS_WIDTH-1) || (SIM_ONLY != 0))
- calib_done_tmp[3] <= 1'b1;
- else
- // need for VHDL simulation to prevent out-of-index error
- next_count_gate <= count_gate + 1;
- end else begin
- cal4_idel_adj_cnt <= cal4_idel_adj_cnt - 1;
- cal4_dlyce_gate <= 1'b1;
- // whether inc or dec depends on whether left or right edge found
- cal4_dlyinc_gate <= cal4_idel_adj_inc;
- end
-
- // wait for IDELAY output to settle after decrement. Check current
- // COUNT_GATE value and decide if we're done
- CAL4_DONE:
- if (!idel_set_wait) begin
- count_gate <= next_count_gate;
- if (calib_done_tmp[3]) begin
- calib_done[3] <= 1'b1;
- cal4_state <= CAL4_IDLE;
- end else begin
- // request auto-refresh after every DQS group calibrated to
- // avoid tRAS violation
- cal4_ref_req <= 1'b1;
- if (calib_ref_done)
- cal4_state <= CAL4_INIT;
- end
- end
- endcase
- end
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_idelay_ctrl.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_idelay_ctrl.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_idelay_ctrl.v (nonexistent)
@@ -1,87 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_idelay_ctrl.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module instantiates the IDELAYCTRL primitive of the Virtex-5 device
-// which continuously calibrates the IDELAY elements in the region in case of
-// varying operating conditions. It takes a 200MHz clock as an input
-//Reference:
-//Revision History:
-// Rev 1.1 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
-// on IOELAYCTRL primitive. Generate logic on IDELAYCTRL removed
-// since tools will replicate idelactrl primitives.PK. 11/27/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_idelay_ctrl #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter IODELAY_GRP = "IODELAY_MIG"
- )
-
- (
- input clk200,
- input rst200,
- output idelay_ctrl_rdy
- );
-
- (* IODELAY_GROUP = IODELAY_GRP *) IDELAYCTRL u_idelayctrl
- (
- .RDY(idelay_ctrl_rdy),
- .REFCLK(clk200),
- .RST(rst200)
- );
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_top.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_top.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_top.v (nonexistent)
@@ -1,181 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_usr_top.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Mon Aug 28 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module interfaces with the user. The user should provide the data
-// and various commands.
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_usr_top #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter CS_BITS = 0,
- parameter COL_WIDTH = 10,
- parameter DQ_WIDTH = 72,
- parameter DQ_PER_DQS = 8,
- parameter APPDATA_WIDTH = 144,
- parameter ECC_ENABLE = 0,
- parameter DQS_WIDTH = 9,
- parameter ROW_WIDTH = 14
- )
- (
- input clk0,
- input clk90,
- input rst0,
- input [DQ_WIDTH-1:0] rd_data_in_rise,
- input [DQ_WIDTH-1:0] rd_data_in_fall,
- input [DQS_WIDTH-1:0] phy_calib_rden,
- input [DQS_WIDTH-1:0] phy_calib_rden_sel,
- output rd_data_valid,
- output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
- input [2:0] app_af_cmd,
- input [30:0] app_af_addr,
- input app_af_wren,
- input ctrl_af_rden,
- output [2:0] af_cmd,
- output [30:0] af_addr,
- output af_empty,
- output app_af_afull,
- output [1:0] rd_ecc_error,
- input app_wdf_wren,
- input [APPDATA_WIDTH-1:0] app_wdf_data,
- input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
- input wdf_rden,
- output app_wdf_afull,
- output [(2*DQ_WIDTH)-1:0] wdf_data,
- output [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data
- );
-
- wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_fall;
- wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_rise;
-
- //***************************************************************************
-
- assign rd_data_fifo_out = {i_rd_data_fifo_out_fall,
- i_rd_data_fifo_out_rise};
-
- // read data de-skew and ECC calculation
- ddr2_usr_rd #
- (
- .DQ_PER_DQS (DQ_PER_DQS),
- .ECC_ENABLE (ECC_ENABLE),
- .APPDATA_WIDTH (APPDATA_WIDTH),
- .DQS_WIDTH (DQS_WIDTH)
- )
- u_usr_rd
- (
- .clk0 (clk0),
- .rst0 (rst0),
- .rd_data_in_rise (rd_data_in_rise),
- .rd_data_in_fall (rd_data_in_fall),
- .rd_ecc_error (rd_ecc_error),
- .ctrl_rden (phy_calib_rden),
- .ctrl_rden_sel (phy_calib_rden_sel),
- .rd_data_valid (rd_data_valid),
- .rd_data_out_rise (i_rd_data_fifo_out_rise),
- .rd_data_out_fall (i_rd_data_fifo_out_fall)
- );
-
- // Command/Addres FIFO
- ddr2_usr_addr_fifo #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .CS_BITS (CS_BITS),
- .ROW_WIDTH (ROW_WIDTH)
- )
- u_usr_addr_fifo
- (
- .clk0 (clk0),
- .rst0 (rst0),
- .app_af_cmd (app_af_cmd),
- .app_af_addr (app_af_addr),
- .app_af_wren (app_af_wren),
- .ctrl_af_rden (ctrl_af_rden),
- .af_cmd (af_cmd),
- .af_addr (af_addr),
- .af_empty (af_empty),
- .app_af_afull (app_af_afull)
- );
-
- ddr2_usr_wr #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .CS_BITS (CS_BITS),
- .DQ_WIDTH (DQ_WIDTH),
- .APPDATA_WIDTH (APPDATA_WIDTH),
- .ECC_ENABLE (ECC_ENABLE),
- .ROW_WIDTH (ROW_WIDTH)
- )
- u_usr_wr
- (
- .clk0 (clk0),
- .clk90 (clk90),
- .rst0 (rst0),
- .app_wdf_wren (app_wdf_wren),
- .app_wdf_data (app_wdf_data),
- .app_wdf_mask_data (app_wdf_mask_data),
- .wdf_rden (wdf_rden),
- .app_wdf_afull (app_wdf_afull),
- .wdf_data (wdf_data),
- .wdf_mask_data (wdf_mask_data)
- );
-
-endmodule
\ No newline at end of file
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_rd.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_rd.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_rd.v (nonexistent)
@@ -1,297 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_usr_rd.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Tue Aug 29 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// The delay between the read data with respect to the command issued is
-// calculted in terms of no. of clocks. This data is then stored into the
-// FIFOs and then read back and given as the ouput for comparison.
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_usr_rd #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter DQ_PER_DQS = 8,
- parameter DQS_WIDTH = 9,
- parameter APPDATA_WIDTH = 144,
- parameter ECC_WIDTH = 72,
- parameter ECC_ENABLE = 0
- )
- (
- input clk0,
- input rst0,
- input [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_rise,
- input [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_fall,
- input [DQS_WIDTH-1:0] ctrl_rden,
- input [DQS_WIDTH-1:0] ctrl_rden_sel,
- output reg [1:0] rd_ecc_error,
- output rd_data_valid,
- output reg [(APPDATA_WIDTH/2)-1:0] rd_data_out_rise,
- output reg [(APPDATA_WIDTH/2)-1:0] rd_data_out_fall
- );
-
- // determine number of FIFO72's to use based on data width
- localparam RDF_FIFO_NUM = ((APPDATA_WIDTH/2)+63)/64;
-
- reg [DQS_WIDTH-1:0] ctrl_rden_r;
- wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data;
- reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_fall_r;
- reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_rise_r;
- wire rden;
- reg [DQS_WIDTH-1:0] rden_sel_r
- /* synthesis syn_preserve=1 */;
- wire [DQS_WIDTH-1:0] rden_sel_mux;
- wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data;
-
- // ECC specific signals
- wire [((RDF_FIFO_NUM -1) *2)+1:0] db_ecc_error;
- reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data_r;
- reg fifo_rden_r0;
- reg fifo_rden_r1;
- reg fifo_rden_r2;
- reg fifo_rden_r3;
- reg fifo_rden_r4;
- reg fifo_rden_r5;
- reg fifo_rden_r6;
- wire [(APPDATA_WIDTH/2)-1:0] rd_data_out_fall_temp;
- wire [(APPDATA_WIDTH/2)-1:0] rd_data_out_rise_temp;
- reg rst_r;
- reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data_r;
- wire [((RDF_FIFO_NUM -1) *2)+1:0] sb_ecc_error;
-
-
- //***************************************************************************
-
- always @(posedge clk0) begin
- rden_sel_r <= ctrl_rden_sel;
- ctrl_rden_r <= ctrl_rden;
- rd_data_in_rise_r <= rd_data_in_rise;
- rd_data_in_fall_r <= rd_data_in_fall;
- end
-
- // Instantiate primitive to allow this flop to be attached to multicycle
- // path constraint in UCF. Multicycle path allowed for data from read FIFO.
- // This is the same signal as RDEN_SEL_R, but is only used to select data
- // (does not affect control signals)
- genvar rd_i;
- generate
- for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rden_sel_mux
- FDRSE u_ff_rden_sel_mux
- (
- .Q (rden_sel_mux[rd_i]),
- .C (clk0),
- .CE (1'b1),
- .D (ctrl_rden_sel[rd_i]),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve=1 */;
- end
- endgenerate
-
- // determine correct read data valid signal timing
- assign rden = (rden_sel_r[0]) ? ctrl_rden[0] : ctrl_rden_r[0];
-
- // assign data based on the skew
- genvar data_i;
- generate
- for(data_i = 0; data_i < DQS_WIDTH; data_i = data_i+1) begin: gen_data
- assign rise_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
- (data_i*DQ_PER_DQS)]
- = (rden_sel_mux[data_i]) ?
- rd_data_in_rise[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1) :
- (data_i*DQ_PER_DQS)] :
- rd_data_in_rise_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
- (data_i*DQ_PER_DQS)];
- assign fall_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
- (data_i*DQ_PER_DQS)]
- = (rden_sel_mux[data_i]) ?
- rd_data_in_fall[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
- (data_i*DQ_PER_DQS)] :
- rd_data_in_fall_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
- (data_i*DQ_PER_DQS)];
- end
- endgenerate
-
- // Generate RST for FIFO reset AND for read/write enable:
- // ECC FIFO always being read from and written to
- always @(posedge clk0)
- rst_r <= rst0;
-
- genvar rdf_i;
- generate
- if (ECC_ENABLE) begin
- always @(posedge clk0) begin
- rd_ecc_error[0] <= (|sb_ecc_error) & fifo_rden_r5;
- rd_ecc_error[1] <= (|db_ecc_error) & fifo_rden_r5;
- rd_data_out_rise <= rd_data_out_rise_temp;
- rd_data_out_fall <= rd_data_out_fall_temp;
- rise_data_r <= rise_data;
- fall_data_r <= fall_data;
- end
-
- // can use any of the read valids, they're all delayed by same amount
- assign rd_data_valid = fifo_rden_r6;
-
- // delay read valid to take into account max delay difference btw
- // the read enable coming from the different DQS groups
- always @(posedge clk0) begin
- if (rst0) begin
- fifo_rden_r0 <= 1'b0;
- fifo_rden_r1 <= 1'b0;
- fifo_rden_r2 <= 1'b0;
- fifo_rden_r3 <= 1'b0;
- fifo_rden_r4 <= 1'b0;
- fifo_rden_r5 <= 1'b0;
- fifo_rden_r6 <= 1'b0;
- end else begin
- fifo_rden_r0 <= rden;
- fifo_rden_r1 <= fifo_rden_r0;
- fifo_rden_r2 <= fifo_rden_r1;
- fifo_rden_r3 <= fifo_rden_r2;
- fifo_rden_r4 <= fifo_rden_r3;
- fifo_rden_r5 <= fifo_rden_r4;
- fifo_rden_r6 <= fifo_rden_r5;
- end
- end
-
- for (rdf_i = 0; rdf_i < RDF_FIFO_NUM; rdf_i = rdf_i + 1) begin: gen_rdf
-
- FIFO36_72 # // rise fifo
- (
- .ALMOST_EMPTY_OFFSET (9'h007),
- .ALMOST_FULL_OFFSET (9'h00F),
- .DO_REG (1), // extra CC output delay
- .EN_ECC_WRITE ("FALSE"),
- .EN_ECC_READ ("TRUE"),
- .EN_SYN ("FALSE"),
- .FIRST_WORD_FALL_THROUGH ("FALSE")
- )
- u_rdf
- (
- .ALMOSTEMPTY (),
- .ALMOSTFULL (),
- .DBITERR (db_ecc_error[rdf_i + rdf_i]),
- .DO (rd_data_out_rise_temp[(64*(rdf_i+1))-1:
- (64 *rdf_i)]),
- .DOP (),
- .ECCPARITY (),
- .EMPTY (),
- .FULL (),
- .RDCOUNT (),
- .RDERR (),
- .SBITERR (sb_ecc_error[rdf_i + rdf_i]),
- .WRCOUNT (),
- .WRERR (),
- .DI (rise_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
- (64 *rdf_i)+(rdf_i*8)]),
- .DIP (rise_data_r[(72*(rdf_i+1))-1:
- (64*(rdf_i+1))+ (8*rdf_i)]),
- .RDCLK (clk0),
- .RDEN (~rst_r),
- .RST (rst_r),
- .WRCLK (clk0),
- .WREN (~rst_r)
- );
-
- FIFO36_72 # // fall_fifo
- (
- .ALMOST_EMPTY_OFFSET (9'h007),
- .ALMOST_FULL_OFFSET (9'h00F),
- .DO_REG (1), // extra CC output delay
- .EN_ECC_WRITE ("FALSE"),
- .EN_ECC_READ ("TRUE"),
- .EN_SYN ("FALSE"),
- .FIRST_WORD_FALL_THROUGH ("FALSE")
- )
- u_rdf1
- (
- .ALMOSTEMPTY (),
- .ALMOSTFULL (),
- .DBITERR (db_ecc_error[(rdf_i+1) + rdf_i]),
- .DO (rd_data_out_fall_temp[(64*(rdf_i+1))-1:
- (64 *rdf_i)]),
- .DOP (),
- .ECCPARITY (),
- .EMPTY (),
- .FULL (),
- .RDCOUNT (),
- .RDERR (),
- .SBITERR (sb_ecc_error[(rdf_i+1) + rdf_i]),
- .WRCOUNT (),
- .WRERR (),
- .DI (fall_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
- (64*rdf_i)+(rdf_i*8)]),
- .DIP (fall_data_r[(72*(rdf_i+1))-1:
- (64*(rdf_i+1))+ (8*rdf_i)]),
- .RDCLK (clk0),
- .RDEN (~rst_r),
- .RST (rst_r), // or can use rst0
- .WRCLK (clk0),
- .WREN (~rst_r)
- );
- end
- end else begin
- assign rd_data_valid = fifo_rden_r0;
- always @(posedge clk0) begin
- rd_data_out_rise <= rise_data;
- rd_data_out_fall <= fall_data;
- fifo_rden_r0 <= rden;
- end
- end
- endgenerate
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_dqs_iob.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_dqs_iob.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_dqs_iob.v (nonexistent)
@@ -1,266 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_phy_dqs_iob.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module places the data strobes in the IOBs.
-//Reference:
-//Revision History:
-// Rev 1.1 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
-// Rev 1.2 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
-// on IODELAY primitives. PK. 11/27/08
-// Rev 1.3 - IDDR primitve (u_iddr_dq_ce) is replaced with a negative-edge
-// triggered flip-flop. PK. 03/20/09
-// Rev 1.4 - To fix CR 540201, S and syn_preserve attributes are added
-// for dqs_oe_n_r. PK. 01/08/10
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_phy_dqs_iob #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter DDR_TYPE = 1,
- parameter HIGH_PERFORMANCE_MODE = "TRUE",
- parameter IODELAY_GRP = "IODELAY_MIG"
- )
- (
- input clk0,
- input clkdiv0,
- input rst0,
- input dlyinc_dqs,
- input dlyce_dqs,
- input dlyrst_dqs,
- input dlyinc_gate,
- input dlyce_gate,
- input dlyrst_gate,
- input dqs_oe_n,
- input dqs_rst_n,
- input en_dqs,
- inout ddr_dqs,
- inout ddr_dqs_n,
- output dq_ce,
- output delayed_dqs
- );
-
- wire clk180;
- wire dqs_bufio;
-
- wire dqs_ibuf;
- wire dqs_idelay;
- wire dqs_oe_n_delay;
- (* S = "TRUE" *) wire dqs_oe_n_r /* synthesis syn_preserve = 1*/;
- wire dqs_rst_n_delay;
- reg dqs_rst_n_r /* synthesis syn_preserve = 1*/;
- wire dqs_out;
- wire en_dqs_sync /* synthesis syn_keep = 1 */;
-
- // for simulation only. Synthesis should ignore this delay
- localparam DQS_NET_DELAY = 0.8;
-
- assign clk180 = ~clk0;
-
- // add delta delay to inputs clocked by clk180 to avoid delta-delay
- // simulation issues
- assign dqs_rst_n_delay = dqs_rst_n;
- assign dqs_oe_n_delay = dqs_oe_n;
-
- //***************************************************************************
- // DQS input-side resources:
- // - IODELAY (pad -> IDELAY)
- // - BUFIO (IDELAY -> BUFIO)
- //***************************************************************************
-
- // Route DQS from PAD to IDELAY
- (* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
- (
- .DELAY_SRC("I"),
- .IDELAY_TYPE("VARIABLE"),
- .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE),
- .IDELAY_VALUE(0),
- .ODELAY_VALUE(0)
- )
- u_idelay_dqs
- (
- .DATAOUT (dqs_idelay),
- .C (clkdiv0),
- .CE (dlyce_dqs),
- .DATAIN (),
- .IDATAIN (dqs_ibuf),
- .INC (dlyinc_dqs),
- .ODATAIN (),
- .RST (dlyrst_dqs),
- .T ()
- );
-
- // From IDELAY to BUFIO
- BUFIO u_bufio_dqs
- (
- .I (dqs_idelay),
- .O (dqs_bufio)
- );
-
- // To model additional delay of DQS BUFIO + gating network
- // for behavioral simulation. Make sure to select a delay number smaller
- // than half clock cycle (otherwise output will not track input changes
- // because of inertial delay). Duplicate to avoid delta delay issues.
- assign #(DQS_NET_DELAY) i_delayed_dqs = dqs_bufio;
- assign #(DQS_NET_DELAY) delayed_dqs = dqs_bufio;
-
- //***************************************************************************
- // DQS gate circuit (not supported for all controllers)
- //***************************************************************************
-
- // Gate routing:
- // en_dqs -> IDELAY -> en_dqs_sync -> IDDR.S -> dq_ce ->
- // capture IDDR.CE
-
- // Delay CE control so that it's in phase with delayed DQS
- (* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
- (
- .DELAY_SRC ("DATAIN"),
- .IDELAY_TYPE ("VARIABLE"),
- .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
- .IDELAY_VALUE (0),
- .ODELAY_VALUE (0)
- )
- u_iodelay_dq_ce
- (
- .DATAOUT (en_dqs_sync),
- .C (clkdiv0),
- .CE (dlyce_gate),
- .DATAIN (en_dqs),
- .IDATAIN (),
- .INC (dlyinc_gate),
- .ODATAIN (),
- .RST (dlyrst_gate),
- .T ()
- );
-
- // Generate sync'ed CE to DQ IDDR's using a negative-edge triggered flip-flop
- // clocked by DQS. This flop should be locked to the IOB flip-flop at the same
- // site as IODELAY u_idelay_dqs in order to use the dedicated route from
- // the IODELAY to flip-flop (to keep this route as short as possible)
- (* IOB = "FORCE" *) FDCPE_1 #
- (
- .INIT(1'b0)
- )
- u_iddr_dq_ce
- (
- .Q (dq_ce),
- .C (i_delayed_dqs),
- .CE (1'b1),
- .CLR (1'b0),
- .D (en_dqs_sync),
- .PRE (en_dqs_sync)
- ) /* synthesis syn_useioff = 1 */
- /* synthesis syn_replicate = 0 */;
-
- //***************************************************************************
- // DQS output-side resources
- //***************************************************************************
-
- // synthesis attribute keep of dqs_rst_n_r is "true"
- always @(posedge clk180)
- dqs_rst_n_r <= dqs_rst_n_delay;
-
- ODDR #
- (
- .SRTYPE("SYNC"),
- .DDR_CLK_EDGE("OPPOSITE_EDGE")
- )
- u_oddr_dqs
- (
- .Q (dqs_out),
- .C (clk180),
- .CE (1'b1),
- .D1 (dqs_rst_n_r), // keep output deasserted for write preamble
- .D2 (1'b0),
- .R (1'b0),
- .S (1'b0)
- );
-
- (* IOB = "FORCE" *) FDP u_tri_state_dqs
- (
- .D (dqs_oe_n_delay),
- .Q (dqs_oe_n_r),
- .C (clk180),
- .PRE (rst0)
- ) /* synthesis syn_useioff = 1 */;
-
- //***************************************************************************
-
- // use either single-ended (for DDR1) or differential (for DDR2) DQS input
-
- generate
- if (DDR_TYPE > 0) begin: gen_dqs_iob_ddr2
- IOBUFDS u_iobuf_dqs
- (
- .O (dqs_ibuf),
- .IO (ddr_dqs),
- .IOB (ddr_dqs_n),
- .I (dqs_out),
- .T (dqs_oe_n_r)
- );
- end else begin: gen_dqs_iob_ddr1
- IOBUF u_iobuf_dqs
- (
- .O (dqs_ibuf),
- .IO (ddr_dqs),
- .I (dqs_out),
- .T (dqs_oe_n_r)
- );
- end
- endgenerate
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_top.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_top.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_top.v (nonexistent)
@@ -1,276 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_top.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// System level module. This level contains just the memory controller.
-// This level will be intiantated when the user wants to remove the
-// synthesizable test bench, IDELAY control block and the clock
-// generation modules.
-//Reference:
-//Revision History:
-// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
-// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
-// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_top #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2, // # of memory bank addr bits
- parameter CKE_WIDTH = 1, // # of memory clock enable outputs
- parameter CLK_WIDTH = 1, // # of clock outputs
- parameter COL_WIDTH = 10, // # of memory column bits
- parameter CS_NUM = 1, // # of separate memory chip selects
- parameter CS_BITS = 0, // set to log2(CS_NUM) (rounded up)
- parameter CS_WIDTH = 1, // # of total memory chip selects
- parameter USE_DM_PORT = 1, // enable Data Mask (=1 enable)
- parameter DM_WIDTH = 9, // # of data mask bits
- parameter DQ_WIDTH = 72, // # of data width
- parameter DQ_BITS = 7, // set to log2(DQS_WIDTH*DQ_PER_DQS)
- parameter DQ_PER_DQS = 8, // # of DQ data bits per strobe
- parameter DQS_WIDTH = 9, // # of DQS strobes
- parameter DQS_BITS = 4, // set to log2(DQS_WIDTH)
- parameter HIGH_PERFORMANCE_MODE = "TRUE", // IODELAY Performance Mode
- parameter IODELAY_GRP = "IODELAY_MIG", // IODELAY Group Name
- parameter ODT_WIDTH = 1, // # of memory on-die term enables
- parameter ROW_WIDTH = 14, // # of memory row & # of addr bits
- parameter APPDATA_WIDTH = 144, // # of usr read/write data bus bits
- parameter ADDITIVE_LAT = 0, // additive write latency
- parameter BURST_LEN = 4, // burst length (in double words)
- parameter BURST_TYPE = 0, // burst type (=0 seq; =1 interlved)
- parameter CAS_LAT = 5, // CAS latency
- parameter ECC_ENABLE = 0, // enable ECC (=1 enable)
- parameter ODT_TYPE = 1, // ODT (=0(none),=1(75),=2(150),=3(50))
- parameter MULTI_BANK_EN = 1, // enable bank management
- parameter TWO_T_TIME_EN = 0, // 2t timing for unbuffered dimms
- parameter REDUCE_DRV = 0, // reduced strength mem I/O (=1 yes)
- parameter REG_ENABLE = 1, // registered addr/ctrl (=1 yes)
- parameter TREFI_NS = 7800, // auto refresh interval (ns)
- parameter TRAS = 40000, // active->precharge delay
- parameter TRCD = 15000, // active->read/write delay
- parameter TRFC = 105000, // ref->ref, ref->active delay
- parameter TRP = 15000, // precharge->command delay
- parameter TRTP = 7500, // read->precharge delay
- parameter TWR = 15000, // used to determine wr->prech
- parameter TWTR = 10000, // write->read delay
- parameter CLK_PERIOD = 3000, // Core/Mem clk period (in ps)
- parameter SIM_ONLY = 0, // = 1 to skip power up delay
- parameter DEBUG_EN = 0, // Enable debug signals/controls
- parameter FPGA_SPEED_GRADE = 2 // FPGA Speed Grade
- )
- (
- input clk0,
- input clk90,
- input clkdiv0,
- input rst0,
- input rst90,
- input rstdiv0,
- input [2:0] app_af_cmd,
- input [30:0] app_af_addr,
- input app_af_wren,
- input app_wdf_wren,
- input [APPDATA_WIDTH-1:0] app_wdf_data,
- input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
- output app_af_afull,
- output app_wdf_afull,
- output rd_data_valid,
- output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
- output [1:0] rd_ecc_error,
- output phy_init_done,
- output [CLK_WIDTH-1:0] ddr2_ck,
- output [CLK_WIDTH-1:0] ddr2_ck_n,
- output [ROW_WIDTH-1:0] ddr2_a,
- output [BANK_WIDTH-1:0] ddr2_ba,
- output ddr2_ras_n,
- output ddr2_cas_n,
- output ddr2_we_n,
- output [CS_WIDTH-1:0] ddr2_cs_n,
- output [CKE_WIDTH-1:0] ddr2_cke,
- output [ODT_WIDTH-1:0] ddr2_odt,
- output [DM_WIDTH-1:0] ddr2_dm,
- inout [DQS_WIDTH-1:0] ddr2_dqs,
- inout [DQS_WIDTH-1:0] ddr2_dqs_n,
- inout [DQ_WIDTH-1:0] ddr2_dq,
- // Debug signals (optional use)
- input dbg_idel_up_all,
- input dbg_idel_down_all,
- input dbg_idel_up_dq,
- input dbg_idel_down_dq,
- input dbg_idel_up_dqs,
- input dbg_idel_down_dqs,
- input dbg_idel_up_gate,
- input dbg_idel_down_gate,
- input [DQ_BITS-1:0] dbg_sel_idel_dq,
- input dbg_sel_all_idel_dq,
- input [DQS_BITS:0] dbg_sel_idel_dqs,
- input dbg_sel_all_idel_dqs,
- input [DQS_BITS:0] dbg_sel_idel_gate,
- input dbg_sel_all_idel_gate,
- output [3:0] dbg_calib_done,
- output [3:0] dbg_calib_err,
- output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
- output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
- output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
- output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
- );
-
- // memory initialization/control logic
- ddr2_mem_if_top #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .CKE_WIDTH (CKE_WIDTH),
- .CLK_WIDTH (CLK_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .CS_BITS (CS_BITS),
- .CS_NUM (CS_NUM),
- .CS_WIDTH (CS_WIDTH),
- .USE_DM_PORT (USE_DM_PORT),
- .DM_WIDTH (DM_WIDTH),
- .DQ_WIDTH (DQ_WIDTH),
- .DQ_BITS (DQ_BITS),
- .DQ_PER_DQS (DQ_PER_DQS),
- .DQS_BITS (DQS_BITS),
- .DQS_WIDTH (DQS_WIDTH),
- .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
- .IODELAY_GRP (IODELAY_GRP),
- .ODT_WIDTH (ODT_WIDTH),
- .ROW_WIDTH (ROW_WIDTH),
- .APPDATA_WIDTH (APPDATA_WIDTH),
- .ADDITIVE_LAT (ADDITIVE_LAT),
- .BURST_LEN (BURST_LEN),
- .BURST_TYPE (BURST_TYPE),
- .CAS_LAT (CAS_LAT),
- .ECC_ENABLE (ECC_ENABLE),
- .MULTI_BANK_EN (MULTI_BANK_EN),
- .TWO_T_TIME_EN (TWO_T_TIME_EN),
- .ODT_TYPE (ODT_TYPE),
- .DDR_TYPE (1),
- .REDUCE_DRV (REDUCE_DRV),
- .REG_ENABLE (REG_ENABLE),
- .TREFI_NS (TREFI_NS),
- .TRAS (TRAS),
- .TRCD (TRCD),
- .TRFC (TRFC),
- .TRP (TRP),
- .TRTP (TRTP),
- .TWR (TWR),
- .TWTR (TWTR),
- .CLK_PERIOD (CLK_PERIOD),
- .SIM_ONLY (SIM_ONLY),
- .DEBUG_EN (DEBUG_EN),
- .FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
- )
- u_mem_if_top
- (
- .clk0 (clk0),
- .clk90 (clk90),
- .clkdiv0 (clkdiv0),
- .rst0 (rst0),
- .rst90 (rst90),
- .rstdiv0 (rstdiv0),
- .app_af_cmd (app_af_cmd),
- .app_af_addr (app_af_addr),
- .app_af_wren (app_af_wren),
- .app_wdf_wren (app_wdf_wren),
- .app_wdf_data (app_wdf_data),
- .app_wdf_mask_data (app_wdf_mask_data),
- .app_af_afull (app_af_afull),
- .app_wdf_afull (app_wdf_afull),
- .rd_data_valid (rd_data_valid),
- .rd_data_fifo_out (rd_data_fifo_out),
- .rd_ecc_error (rd_ecc_error),
- .phy_init_done (phy_init_done),
- .ddr_ck (ddr2_ck),
- .ddr_ck_n (ddr2_ck_n),
- .ddr_addr (ddr2_a),
- .ddr_ba (ddr2_ba),
- .ddr_ras_n (ddr2_ras_n),
- .ddr_cas_n (ddr2_cas_n),
- .ddr_we_n (ddr2_we_n),
- .ddr_cs_n (ddr2_cs_n),
- .ddr_cke (ddr2_cke),
- .ddr_odt (ddr2_odt),
- .ddr_dm (ddr2_dm),
- .ddr_dqs (ddr2_dqs),
- .ddr_dqs_n (ddr2_dqs_n),
- .ddr_dq (ddr2_dq),
- .dbg_idel_up_all (dbg_idel_up_all),
- .dbg_idel_down_all (dbg_idel_down_all),
- .dbg_idel_up_dq (dbg_idel_up_dq),
- .dbg_idel_down_dq (dbg_idel_down_dq),
- .dbg_idel_up_dqs (dbg_idel_up_dqs),
- .dbg_idel_down_dqs (dbg_idel_down_dqs),
- .dbg_idel_up_gate (dbg_idel_up_gate),
- .dbg_idel_down_gate (dbg_idel_down_gate),
- .dbg_sel_idel_dq (dbg_sel_idel_dq),
- .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
- .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
- .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
- .dbg_sel_idel_gate (dbg_sel_idel_gate),
- .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
- .dbg_calib_done (dbg_calib_done),
- .dbg_calib_err (dbg_calib_err),
- .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
- .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
- .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
- .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
- .dbg_calib_rden_dly (dbg_calib_rden_dly),
- .dbg_calib_gate_dly (dbg_calib_gate_dly)
- );
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_ctrl.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_ctrl.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_ctrl.v (nonexistent)
@@ -1,1230 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_ctrl.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 30 2006
-// \___\/\___\
-//
-//
-//Device: Virtex-5
-//Design Name: DDR/DDR2
-//Purpose:
-// This module is the main control logic of the memory interface. All
-// commands are issued from here according to the burst, CAS Latency and the
-// user commands.
-//Reference:
-//Revision History:
-// Rev 1.2 - Fixed auto refresh to activate bug. KP 11-19-2007
-// Rev 1.3 - For Dual Rank parts support CS logic modified. KP. 05/08/08
-// Rev 1.4 - AUTO_REFRESH_WAIT state modified for Auto Refresh flag asserted
-// immediately after calibration is completed. KP. 07/28/08
-// Rev 1.5 - Assignment of bank_valid_r is modified to fix a bug in
-// Bank Management logic. PK. 10/29/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_ctrl #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter COL_WIDTH = 10,
- parameter CS_BITS = 0,
- parameter CS_NUM = 1,
- parameter ROW_WIDTH = 14,
- parameter ADDITIVE_LAT = 0,
- parameter BURST_LEN = 4,
- parameter CAS_LAT = 5,
- parameter ECC_ENABLE = 0,
- parameter REG_ENABLE = 1,
- parameter TREFI_NS = 7800,
- parameter TRAS = 40000,
- parameter TRCD = 15000,
- parameter TRRD = 10000,
- parameter TRFC = 105000,
- parameter TRP = 15000,
- parameter TRTP = 7500,
- parameter TWR = 15000,
- parameter TWTR = 10000,
- parameter CLK_PERIOD = 3000,
- parameter MULTI_BANK_EN = 1,
- parameter TWO_T_TIME_EN = 0,
- parameter DDR_TYPE = 1
- )
- (
- input clk,
- input rst,
- input [2:0] af_cmd,
- input [30:0] af_addr,
- input af_empty,
- input phy_init_done,
- output ctrl_ref_flag,
- output ctrl_af_rden,
- output reg ctrl_wren,
- output reg ctrl_rden,
- output [ROW_WIDTH-1:0] ctrl_addr,
- output [BANK_WIDTH-1:0] ctrl_ba,
- output ctrl_ras_n,
- output ctrl_cas_n,
- output ctrl_we_n,
- output [CS_NUM-1:0] ctrl_cs_n
- );
-
- // input address split into various ranges
- localparam ROW_RANGE_START = COL_WIDTH;
- localparam ROW_RANGE_END = ROW_WIDTH + ROW_RANGE_START - 1;
- localparam BANK_RANGE_START = ROW_RANGE_END + 1;
- localparam BANK_RANGE_END = BANK_WIDTH + BANK_RANGE_START - 1;
- localparam CS_RANGE_START = BANK_RANGE_START + BANK_WIDTH;
- localparam CS_RANGE_END = CS_BITS + CS_RANGE_START - 1;
- // compare address (for determining bank/row hits) split into various ranges
- // (compare address doesn't include column bits)
- localparam CMP_WIDTH = CS_BITS + BANK_WIDTH + ROW_WIDTH;
- localparam CMP_ROW_RANGE_START = 0;
- localparam CMP_ROW_RANGE_END = ROW_WIDTH + CMP_ROW_RANGE_START - 1;
- localparam CMP_BANK_RANGE_START = CMP_ROW_RANGE_END + 1;
- localparam CMP_BANK_RANGE_END = BANK_WIDTH + CMP_BANK_RANGE_START - 1;
- localparam CMP_CS_RANGE_START = CMP_BANK_RANGE_END + 1;
- localparam CMP_CS_RANGE_END = CS_BITS + CMP_CS_RANGE_START-1;
-
- localparam BURST_LEN_DIV2 = BURST_LEN / 2;
- localparam OPEN_BANK_NUM = 4;
- localparam CS_BITS_FIX = (CS_BITS == 0) ? 1 : CS_BITS;
-
- // calculation counters based on clock cycle and memory parameters
- // TRAS: ACTIVE->PRECHARGE interval - 2
- localparam integer TRAS_CYC = (TRAS + CLK_PERIOD)/CLK_PERIOD;
- // TRCD: ACTIVE->READ/WRITE interval - 3 (for DDR2 factor in ADD_LAT)
- localparam integer TRRD_CYC = (TRRD + CLK_PERIOD)/CLK_PERIOD;
- localparam integer TRCD_CYC = (((TRCD + CLK_PERIOD)/CLK_PERIOD) >
- ADDITIVE_LAT )?
- ((TRCD+CLK_PERIOD)/ CLK_PERIOD) - ADDITIVE_LAT : 0;
- // TRFC: REFRESH->REFRESH, REFRESH->ACTIVE interval - 2
- localparam integer TRFC_CYC = (TRFC + CLK_PERIOD)/CLK_PERIOD;
- // TRP: PRECHARGE->COMMAND interval - 2
- // for precharge all add 1 extra clock cycle
- localparam integer TRP_CYC = ((TRP + CLK_PERIOD)/CLK_PERIOD) +1;
- // TRTP: READ->PRECHARGE interval - 2 (Al + BL/2 + (max (TRTP, 2tck))-2
- localparam integer TRTP_TMP_MIN = (((TRTP + CLK_PERIOD)/CLK_PERIOD) >= 2)?
- ((TRTP + CLK_PERIOD)/CLK_PERIOD) : 2;
- localparam integer TRTP_CYC = TRTP_TMP_MIN + ADDITIVE_LAT
- + BURST_LEN_DIV2 - 2;
- // TWR: WRITE->PRECHARGE interval - 2
- localparam integer WR_LAT = (DDR_TYPE > 0) ? CAS_LAT + ADDITIVE_LAT - 1 : 1;
- localparam integer TWR_CYC = ((TWR + CLK_PERIOD)/CLK_PERIOD) +
- WR_LAT + BURST_LEN_DIV2 ;
- // TWTR: WRITE->READ interval - 3 (for DDR1, TWTR = 2 clks)
- // DDR2 = CL-1 + BL/2 +TWTR
- localparam integer TWTR_TMP_MIN = ((TWTR + CLK_PERIOD) % CLK_PERIOD)?((TWTR + CLK_PERIOD)/CLK_PERIOD) + 1:(TWTR + CLK_PERIOD)/CLK_PERIOD;
- localparam integer TWTR_CYC = (DDR_TYPE > 0) ? (TWTR_TMP_MIN + (CAS_LAT -1)
- + BURST_LEN_DIV2 ): 2;
-
- // TRTW: READ->WRITE interval - 3
- // DDR1: CL + (BL/2)
- // DDR2: (BL/2) + 2. Two more clocks are added to
- // the DDR2 counter to account for the delay in
- // arrival of the DQS during reads (pcb trace + buffer
- // delays + memory parameters).
- localparam TRTW_CYC = (DDR_TYPE > 0) ? BURST_LEN_DIV2 + 4 :
- (CAS_LAT == 25) ? 2 + BURST_LEN_DIV2 : CAS_LAT + BURST_LEN_DIV2;
-
- localparam integer CAS_LAT_RD = (CAS_LAT == 25) ? 2 : CAS_LAT;
-
- // Make sure all values >= 0 (some may be = 0)
- localparam TRAS_COUNT = (TRAS_CYC > 0) ? TRAS_CYC : 0;
- localparam TRCD_COUNT = (TRCD_CYC > 0) ? TRCD_CYC : 0;
- localparam TRRD_COUNT = (TRRD_CYC > 0) ? TRRD_CYC : 0;
- localparam TRFC_COUNT = (TRFC_CYC > 0) ? TRFC_CYC : 0;
- localparam TRP_COUNT = (TRP_CYC > 0) ? TRP_CYC : 0;
- localparam TRTP_COUNT = (TRTP_CYC > 0) ? TRTP_CYC : 0;
- localparam TWR_COUNT = (TWR_CYC > 0) ? TWR_CYC : 0;
- localparam TWTR_COUNT = (TWTR_CYC > 0) ? TWTR_CYC : 0;
- localparam TRTW_COUNT = (TRTW_CYC > 0) ? TRTW_CYC : 0;
-
- // Auto refresh interval
- localparam TREFI_COUNT = ((TREFI_NS * 1000)/CLK_PERIOD) - 1;
-
- // memory controller states
- localparam CTRL_IDLE = 5'h00;
- localparam CTRL_PRECHARGE = 5'h01;
- localparam CTRL_PRECHARGE_WAIT = 5'h02;
- localparam CTRL_AUTO_REFRESH = 5'h03;
- localparam CTRL_AUTO_REFRESH_WAIT = 5'h04;
- localparam CTRL_ACTIVE = 5'h05;
- localparam CTRL_ACTIVE_WAIT = 5'h06;
- localparam CTRL_BURST_READ = 5'h07;
- localparam CTRL_READ_WAIT = 5'h08;
- localparam CTRL_BURST_WRITE = 5'h09;
- localparam CTRL_WRITE_WAIT = 5'h0A;
- localparam CTRL_PRECHARGE_WAIT1 = 5'h0B;
-
-
- reg [CMP_WIDTH-1:0] act_addr_r;
- wire [30:0] af_addr_r;
- reg [30:0] af_addr_r1;
- reg [30:0] af_addr_r2;
- reg [30:0] af_addr_r3;
- wire [2:0] af_cmd_r;
- reg [2:0] af_cmd_r1;
- reg [2:0] af_cmd_r2;
- reg af_valid_r;
- reg af_valid_r1;
- reg af_valid_r2;
- reg [CS_BITS_FIX :0] auto_cnt_r;
- reg auto_ref_r;
- reg [(OPEN_BANK_NUM*CMP_WIDTH)-1:0] bank_cmp_addr_r;
- reg [OPEN_BANK_NUM-1:0] bank_hit;
- reg [OPEN_BANK_NUM-1:0] bank_hit_r;
- reg [OPEN_BANK_NUM-1:0] bank_hit_r1;
- reg [OPEN_BANK_NUM-1:0] bank_valid_r;
- reg bank_conflict_r;
- reg conflict_resolved_r;
- reg ctrl_af_rden_r;
- reg conflict_detect_r;
- wire conflict_detect;
- reg cs_change_r;
- reg cs_change_sticky_r;
- reg [ROW_WIDTH-1:0] ddr_addr_r;
- wire [ROW_WIDTH-1:0] ddr_addr_col;
- wire [ROW_WIDTH-1:0] ddr_addr_row;
- reg [BANK_WIDTH-1:0] ddr_ba_r;
- reg ddr_cas_n_r;
- reg [CS_NUM-1:0] ddr_cs_n_r;
- reg ddr_ras_n_r;
- reg ddr_we_n_r;
- reg [4:0] next_state;
- reg no_precharge_wait_r;
- reg no_precharge_r;
- reg no_precharge_r1;
- reg phy_init_done_r;
- reg [4:0] precharge_ok_cnt_r;
- reg precharge_ok_r;
- reg [4:0] ras_cnt_r;
- reg [3:0] rcd_cnt_r;
- reg rcd_cnt_ok_r;
- reg [2:0] rdburst_cnt_r;
- reg rdburst_ok_r;
- reg rdburst_rden_ok_r;
- reg rd_af_flag_r;
- wire rd_flag;
- reg rd_flag_r;
- reg [4:0] rd_to_wr_cnt_r;
- reg rd_to_wr_ok_r;
- reg ref_flag_r;
- reg [11:0] refi_cnt_r;
- reg refi_cnt_ok_r;
- reg rst_r
- /* synthesis syn_preserve = 1 */;
- reg rst_r1
- /* synthesis syn_maxfan = 10 */;
- reg [7:0] rfc_cnt_r;
- reg rfc_ok_r;
- reg [3:0] row_miss;
- reg [3:0] row_conflict_r;
- reg [3:0] rp_cnt_r;
- reg rp_cnt_ok_r;
- reg [CMP_WIDTH-1:0] sb_open_add_r;
- reg [4:0] state_r;
- reg [4:0] state_r1;
- wire sm_rden;
- reg sm_rden_r;
- reg [2:0] trrd_cnt_r;
- reg trrd_cnt_ok_r;
- reg [2:0] two_t_enable_r;
- reg [CS_NUM-1:0] two_t_enable_r1;
- reg [2:0] wrburst_cnt_r;
- reg wrburst_ok_r;
- reg wrburst_wren_ok_r;
- wire wr_flag;
- reg wr_flag_r;
- reg [4:0] wr_to_rd_cnt_r;
- reg wr_to_rd_ok_r;
-
- // XST attributes for local reset "tree"
- // synthesis attribute shreg_extract of rst_r is "no";
- // synthesis attribute shreg_extract of rst_r1 is "no";
- // synthesis attribute equivalent_register_removal of rst_r is "no"
-
- //***************************************************************************
-
- // sm_rden is used to assert read enable to the address FIFO
- assign sm_rden = ((state_r == CTRL_BURST_WRITE) ||
- (state_r == CTRL_BURST_READ)) ;
-
- // assert read flag to the adress FIFO
- assign ctrl_af_rden = sm_rden || rd_af_flag_r;
-
- // local reset "tree" for controller logic only. Create this to ease timing
- // on reset path. Prohibit equivalent register removal on RST_R to prevent
- // "sharing" with other local reset trees (caution: make sure global fanout
- // limit is set to large enough value, otherwise SLICES may be used for
- // fanout control on RST_R.
- always @(posedge clk) begin
- rst_r <= rst;
- rst_r1 <= rst_r;
- end
-
- //*****************************************************************
- // interpret commands from Command/Address FIFO
- //*****************************************************************
-
- assign wr_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b000) ? 1'b1 : 1'b0): 1'b0;
- assign rd_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b001) ? 1'b1 : 1'b0): 1'b0;
-
- always @(posedge clk) begin
- rd_flag_r <= rd_flag;
- wr_flag_r <= wr_flag;
- end
-
- //////////////////////////////////////////////////
- // The data from the address FIFO is fetched and
- // stored in two register stages. The data will be
- // pulled out of the second register stage whenever
- // the state machine can handle new data from the
- // address FIFO.
-
- // This flag is asserted when there is no
- // cmd & address in the pipe. When there is
- // valid cmd & addr from the address FIFO the
- // af_valid signals will be asserted. This flag will
- // be set the cycle af_valid_r is de-asserted.
- always @(posedge clk) begin
- // for simulation purposes - to force CTRL_AF_RDEN low during reset
- if (rst_r1)
- rd_af_flag_r <= 1'd0;
- else if((ctrl_af_rden_r) ||
- (rd_af_flag_r && (af_valid_r || af_valid_r1)))
- rd_af_flag_r <= 1'd0;
- else if (~af_valid_r1 || ~af_valid_r)
- rd_af_flag_r <= 1'd1;
-
- end
-
- // First register stage for the cmd & add from the FIFO.
- // The af_valid_r signal gives the status of the data
- // in this stage. The af_valid_r will be asserted when there
- // is valid data. This register stage will be updated
- // 1. read to the FIFO and the FIFO not empty
- // 2. After write and read states
- // 3. The valid signal is not asserted in the last stage.
- always @(posedge clk) begin
- if (rst_r1)begin
- af_valid_r <= 1'd0;
- end else begin
- if (ctrl_af_rden_r || sm_rden_r || ~af_valid_r1
- || ~af_valid_r2)begin
- af_valid_r <= ctrl_af_rden_r;
- end
- end
- end
-
- // The output register in the FIFO is used. The addr
- // and command are already registered in the FIFO.
- assign af_addr_r = af_addr;
- assign af_cmd_r = af_cmd;
-
- // Second register stage for the cmd & add from the FIFO.
- // The af_valid_r1 signal gives the status of the data
- // in this stage. The af_valid_r will be asserted when there
- // is valid data. This register stage will be updated
- // 1. read to the FIFO and the FIFO not empty and there
- // is no valid data on this stage
- // 2. After write and read states
- // 3. The valid signal is not asserted in the last stage.
- always@(posedge clk) begin
- if (rst_r1)begin
- af_valid_r1 <= 1'd0;
- af_addr_r1 <= {31{1'bx}};
- af_cmd_r1 <= {3{1'bx}};
- end else if (~af_valid_r1 || sm_rden_r ||
- ~af_valid_r2) begin
- af_valid_r1 <= af_valid_r;
- af_addr_r1 <= af_addr_r;
- af_cmd_r1 <= af_cmd_r;
- end
- end
-
- // The state machine uses the address and command in this
- // register stage. The data is fetched from the second
- // register stage whenever the state machine can accept new
- // addr. The conflict flags are also generated based on the
- // second register stage and updated when the new address
- // is loaded for the state machine.
- always@(posedge clk) begin
- if (rst_r1)begin
- af_valid_r2 <= 1'd0;
- af_addr_r2 <= {31{1'bx}};
- af_cmd_r2 <= {3{1'bx}};
- bank_hit_r <= {OPEN_BANK_NUM{1'bx}};
- bank_conflict_r <= 1'bx;
- row_conflict_r <= 4'bx;
- end else if(sm_rden || ~af_valid_r2)begin
- af_valid_r2 <= af_valid_r1;
- af_addr_r2 <= af_addr_r1;
- af_cmd_r2 <= af_cmd_r1;
- if(MULTI_BANK_EN)begin
- bank_hit_r <= bank_hit;
- row_conflict_r <= row_miss;
- bank_conflict_r <= (~(|bank_hit));
- end else begin
- bank_hit_r <= {OPEN_BANK_NUM{1'b0}};
- bank_conflict_r <= 1'd0;
- row_conflict_r[0] <= (af_addr_r1[CS_RANGE_END:ROW_RANGE_START]
- != sb_open_add_r[CMP_WIDTH-1:0]);
- end
- end
- end // always@ (posedge clk)
-
- //detecting cs change for multi chip select case
- generate
- if(CS_NUM > 1) begin: gen_cs_change
- always @(posedge clk) begin
- if(sm_rden || ~af_valid_r2)begin
- cs_change_r <= af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
- af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
- cs_change_sticky_r <=
- af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
- af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
- end else
- cs_change_r <= 1'd0;
- end
- end // block: gen_cs_change
- else begin: gen_cs_0
- always @(posedge clk) begin
- cs_change_r <= 1'd0;
- cs_change_sticky_r <= 1'd0;
- end
- end
- endgenerate
-
- assign conflict_detect = (MULTI_BANK_EN) ?
- ((|(row_conflict_r[3:0] & bank_hit_r[3:0]))
- | bank_conflict_r) & af_valid_r2 :
- row_conflict_r[0] & af_valid_r2;
-
- always @(posedge clk) begin
- conflict_detect_r <= conflict_detect;
- sm_rden_r <= sm_rden;
- af_addr_r3 <= af_addr_r2;
- ctrl_af_rden_r <= ctrl_af_rden & ~af_empty;
- end
-
- // conflict resolved signal. When this signal is asserted
- // the conflict is resolved. The address to be compared
- // for the conflict_resolved_r will be stored in act_add_r
- // when the bank is opened.
- always @(posedge clk) begin
- conflict_resolved_r <= (act_addr_r ==
- af_addr_r2[CS_RANGE_END:ROW_RANGE_START]);
- if((state_r == CTRL_ACTIVE))
- act_addr_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
- end
-
- //***************************************************************************
- // Bank management logic
- // Semi-hardcoded for now for 4 banks
- // will keep multiple banks open if MULTI_BANK_EN is true.
- //***************************************************************************
-
- genvar bank_i;
- generate // if multiple bank option chosen
- if(MULTI_BANK_EN) begin: gen_multi_bank_open
-
- for (bank_i = 0; bank_i < OPEN_BANK_NUM;
- bank_i = bank_i + 1) begin: gen_bank_hit1
- // asserted if bank address match + open bank entry is valid
- always @(*) begin
- bank_hit[bank_i]
- = ((bank_cmp_addr_r[(CMP_WIDTH*(bank_i+1))-1:
- (CMP_WIDTH*bank_i)+ROW_WIDTH] ==
- af_addr_r1[CS_RANGE_END:BANK_RANGE_START]) &&
- bank_valid_r[bank_i]);
- // asserted if row address match (no check for bank entry valid, rely
- // on this term to be used in conjunction with BANK_HIT[])
- row_miss[bank_i]
- = (bank_cmp_addr_r[(CMP_WIDTH*bank_i)+ROW_WIDTH-1:
- (CMP_WIDTH*bank_i)] !=
- af_addr_r1[ROW_RANGE_END:ROW_RANGE_START]);
- end
- end
-
- always @(posedge clk) begin
- no_precharge_wait_r <= bank_valid_r[3] & bank_conflict_r;
- bank_hit_r1 <= bank_hit_r;
- end
-
- always@(*)
- no_precharge_r = ~bank_valid_r[3] & bank_conflict_r;
-
- always@(posedge clk)
- no_precharge_r1 <= no_precharge_r;
-
-
- always @(posedge clk) begin
- // Clear all bank valid bits during AR (i.e. since all banks get
- // precharged during auto-refresh)
- if ((state_r1 == CTRL_AUTO_REFRESH)) begin
- bank_valid_r <= {OPEN_BANK_NUM{1'b0}};
- bank_cmp_addr_r <= {(OPEN_BANK_NUM*CMP_WIDTH-1){1'b0}};
- end else begin
- if (state_r1 == CTRL_ACTIVE) begin
- // 00 is always going to have the latest bank and row.
- bank_cmp_addr_r[CMP_WIDTH-1:0]
- <= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
- // This indicates the bank was activated
- bank_valid_r[0] <= 1'b1;
-
- case ({bank_hit_r1[2:0]})
- 3'b001: begin
- bank_cmp_addr_r[CMP_WIDTH-1:0]
- <= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
- // This indicates the bank was activated
- bank_valid_r[0] <= 1'b1;
- end
- 3'b010: begin //(b0->b1)
- bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
- <= bank_cmp_addr_r[CMP_WIDTH-1:0];
- bank_valid_r[1] <= bank_valid_r[0];
- end
- 3'b100:begin //(b0->b1, b1->b2)
- bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
- <= bank_cmp_addr_r[CMP_WIDTH-1:0];
- bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
- <= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
- bank_valid_r[1] <= bank_valid_r[0];
- bank_valid_r[2] <= bank_valid_r[1];
- end
- default: begin //(b0->b1, b1->b2, b2->b3)
- bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
- <= bank_cmp_addr_r[CMP_WIDTH-1:0];
- bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
- <= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
- bank_cmp_addr_r[(4*CMP_WIDTH)-1:3*CMP_WIDTH]
- <= bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH];
- bank_valid_r[1] <= bank_valid_r[0];
- bank_valid_r[2] <= bank_valid_r[1];
- bank_valid_r[3] <= bank_valid_r[2];
- end
- endcase
- end
- end
- end
- end else begin: gen_single_bank_open // single bank option
- always @(posedge clk) begin
- no_precharge_r <= 1'd0;
- no_precharge_r1 <= 1'd0;
- no_precharge_wait_r <= 1'd0;
- if (rst_r1)
- sb_open_add_r <= {CMP_WIDTH{1'b0}};
- else if (state_r == CTRL_ACTIVE)
- sb_open_add_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
- end
- end
- endgenerate
-
- //***************************************************************************
- // Timing counters
- //***************************************************************************
-
- //*****************************************************************
- // Write and read enable generation for PHY
- //*****************************************************************
-
- // write burst count. Counts from (BL/2 to 1).
- // Also logic for controller write enable.
- always @(posedge clk) begin
- if (state_r == CTRL_BURST_WRITE) begin
- wrburst_cnt_r <= BURST_LEN_DIV2;
- end else if (wrburst_cnt_r >= 3'd1)
- wrburst_cnt_r <= wrburst_cnt_r - 1;
- end // always @ (posedge clk)
-
-
- always @(posedge clk) begin
- if (rst_r1) begin
- ctrl_wren <= 1'b0;
- end else if (state_r == CTRL_BURST_WRITE) begin
- ctrl_wren <= 1'b1;
- end else if (wrburst_wren_ok_r)
- ctrl_wren <= 1'b0;
- end
-
-
- always @(posedge clk) begin
- if ((state_r == CTRL_BURST_WRITE)
- && (BURST_LEN_DIV2 > 2))
- wrburst_ok_r <= 1'd0;
- else if ((wrburst_cnt_r <= 3'd3) ||
- (BURST_LEN_DIV2 <= 2))
- wrburst_ok_r <= 1'b1;
- end
-
- // flag to check when wrburst count has reached
- // a value of 1. This flag is used in the ctrl_wren
- // logic
- always @(posedge clk) begin
- if(wrburst_cnt_r == 3'd2)
- wrburst_wren_ok_r <=1'b1;
- else
- wrburst_wren_ok_r <= 1'b0;
- end
-
-
- // read burst count. Counts from (BL/2 to 1)
- always @(posedge clk) begin
- if (state_r == CTRL_BURST_READ) begin
- rdburst_cnt_r <= BURST_LEN_DIV2;
- end else if (rdburst_cnt_r >= 3'd1)
- rdburst_cnt_r <= rdburst_cnt_r - 1;
- end // always @ (posedge clk)
-
-
- always @(posedge clk) begin
- if (rst_r1) begin
- ctrl_rden <= 1'b0;
- end else if (state_r == CTRL_BURST_READ) begin
- ctrl_rden <= 1'b1;
- end else if (rdburst_rden_ok_r)
- ctrl_rden <= 1'b0;
- end
-
- // the rd_burst_ok_r signal will be asserted one cycle later
- // in multi chip select cases if the back to back read is to
- // different chip selects. The cs_changed_sticky_r signal will
- // be asserted only for multi chip select cases.
- always @(posedge clk) begin
- if ((state_r == CTRL_BURST_READ)
- && (BURST_LEN_DIV2 > 2))
- rdburst_ok_r <= 1'd0;
- else if ((rdburst_cnt_r <=( 3'd3 - cs_change_sticky_r)) ||
- (BURST_LEN_DIV2 <= 2))
- rdburst_ok_r <= 1'b1;
- end
-
- // flag to check when rdburst count has reached
- // a value of 1. This flag is used in the ctrl_rden
- // logic
- always @(posedge clk) begin
- if (rdburst_cnt_r == 3'd2)
- rdburst_rden_ok_r <= 1'b1;
- else
- rdburst_rden_ok_r <= 1'b0;
- end
-
-
- //*****************************************************************
- // Various delay counters
- // The counters are checked for value of <= 3 to determine the
- // if the count values are reached during different commands.
- // It is checked for 3 because
- // 1. The counters are loaded during the state when the command
- // state is reached (+1)
- // 2. After the <= 3 condition is reached the sm takes two cycles
- // to transition to the new command state (+2)
- //*****************************************************************
-
- // tRP count - precharge command period
- always @(posedge clk) begin
- if (state_r == CTRL_PRECHARGE)
- rp_cnt_r <= TRP_COUNT;
- else if (rp_cnt_r != 4'd0)
- rp_cnt_r <= rp_cnt_r - 1;
- end
-
- always @(posedge clk) begin
- if (state_r == CTRL_PRECHARGE)
- rp_cnt_ok_r <= 1'd0;
- else if (rp_cnt_r <= 4'd3)
- rp_cnt_ok_r <= 1'd1;
- end
-
- // tRFC count - refresh-refresh, refresh-active
- always @(posedge clk) begin
- if (state_r == CTRL_AUTO_REFRESH)
- rfc_cnt_r <= TRFC_COUNT;
- else if (rfc_cnt_r != 8'd0)
- rfc_cnt_r <= rfc_cnt_r - 1;
- end
-
- always @(posedge clk) begin
- if (state_r == CTRL_AUTO_REFRESH)
- rfc_ok_r <= 1'b0;
- else if(rfc_cnt_r <= 8'd3)
- rfc_ok_r <= 1'b1;
- end
-
- // tRCD count - active to read/write
- always @(posedge clk) begin
- if (state_r == CTRL_ACTIVE)
- rcd_cnt_r <= TRCD_COUNT;
- else if (rcd_cnt_r != 4'd0)
- rcd_cnt_r <= rcd_cnt_r - 1;
- end
-
- always @(posedge clk) begin
- if ((state_r == CTRL_ACTIVE)
- && (TRCD_COUNT > 2))
- rcd_cnt_ok_r <= 1'd0;
- else if (rcd_cnt_r <= 4'd3)
- rcd_cnt_ok_r <= 1;
- end
-
- // tRRD count - active to active
- always @(posedge clk) begin
- if (state_r == CTRL_ACTIVE)
- trrd_cnt_r <= TRRD_COUNT;
- else if (trrd_cnt_r != 3'd0)
- trrd_cnt_r <= trrd_cnt_r - 1;
- end
-
- always @(posedge clk) begin
- if (state_r == CTRL_ACTIVE)
- trrd_cnt_ok_r <= 1'd0;
- else if (trrd_cnt_r <= 3'd3)
- trrd_cnt_ok_r <= 1;
- end
-
- // tRAS count - active to precharge
- always @(posedge clk) begin
- if (state_r == CTRL_ACTIVE)
- ras_cnt_r <= TRAS_COUNT;
- else if (ras_cnt_r != 5'd0)
- ras_cnt_r <= ras_cnt_r - 1;
- end
-
- // counter for write to prcharge
- // read to precharge and
- // activate to precharge
- // precharge_ok_cnt_r is added with trtp count,
- // there can be cases where the sm can go from
- // activate to read and the act->pre count time
- // would not have been satisfied. The rd->pre
- // time is very less. wr->pre time is almost the
- // same as act-> pre
- always @(posedge clk) begin
- if (rst_r1)
- precharge_ok_cnt_r <= 5'd0;
- else if (state_r == CTRL_BURST_READ) begin
- // assign only if the cnt is < TRTP_COUNT
- if (precharge_ok_cnt_r < TRTP_COUNT)
- precharge_ok_cnt_r <= TRTP_COUNT;
- end else if (state_r == CTRL_BURST_WRITE)
- precharge_ok_cnt_r <= TWR_COUNT;
- else if (state_r == CTRL_ACTIVE)
- if (precharge_ok_cnt_r <= TRAS_COUNT)
- precharge_ok_cnt_r <= TRAS_COUNT;
- else
- precharge_ok_cnt_r <= precharge_ok_cnt_r - 1;
- else if (precharge_ok_cnt_r != 5'd0)
- precharge_ok_cnt_r <= precharge_ok_cnt_r - 1;
- end
-
- always @(posedge clk) begin
- if ((state_r == CTRL_BURST_READ) ||
- (state_r == CTRL_BURST_WRITE)||
- (state_r == CTRL_ACTIVE))
- precharge_ok_r <= 1'd0;
- else if(precharge_ok_cnt_r <= 5'd3)
- precharge_ok_r <=1'd1;
- end
-
- // write to read counter
- // write to read includes : write latency + burst time + tWTR
- always @(posedge clk) begin
- if (rst_r1)
- wr_to_rd_cnt_r <= 5'd0;
- else if (state_r == CTRL_BURST_WRITE)
- wr_to_rd_cnt_r <= (TWTR_COUNT);
- else if (wr_to_rd_cnt_r != 5'd0)
- wr_to_rd_cnt_r <= wr_to_rd_cnt_r - 1;
- end
-
- always @(posedge clk) begin
- if (state_r == CTRL_BURST_WRITE)
- wr_to_rd_ok_r <= 1'd0;
- else if (wr_to_rd_cnt_r <= 5'd3)
- wr_to_rd_ok_r <= 1'd1;
- end
-
- // read to write counter
- always @(posedge clk) begin
- if (rst_r1)
- rd_to_wr_cnt_r <= 5'd0;
- else if (state_r == CTRL_BURST_READ)
- rd_to_wr_cnt_r <= (TRTW_COUNT);
- else if (rd_to_wr_cnt_r != 5'd0)
- rd_to_wr_cnt_r <= rd_to_wr_cnt_r - 1;
- end
-
- always @(posedge clk) begin
- if (state_r == CTRL_BURST_READ)
- rd_to_wr_ok_r <= 1'b0;
- else if (rd_to_wr_cnt_r <= 5'd3)
- rd_to_wr_ok_r <= 1'b1;
- end
-
- always @(posedge clk) begin
- if(refi_cnt_r == (TREFI_COUNT -1))
- refi_cnt_ok_r <= 1'b1;
- else
- refi_cnt_ok_r <= 1'b0;
- end
-
- // auto refresh interval counter in refresh_clk domain
- always @(posedge clk) begin
- if ((rst_r1) || (refi_cnt_ok_r)) begin
- refi_cnt_r <= 12'd0;
- end else begin
- refi_cnt_r <= refi_cnt_r + 1;
- end
- end // always @ (posedge clk)
-
- // auto refresh flag
- always @(posedge clk) begin
- if (refi_cnt_ok_r) begin
- ref_flag_r <= 1'b1;
- end else begin
- ref_flag_r <= 1'b0;
- end
- end // always @ (posedge clk)
-
- assign ctrl_ref_flag = ref_flag_r;
-
- //refresh flag detect
- //auto_ref high indicates auto_refresh requirement
- //auto_ref is held high until auto refresh command is issued.
- always @(posedge clk)begin
- if (rst_r1)
- auto_ref_r <= 1'b0;
- else if (ref_flag_r)
- auto_ref_r <= 1'b1;
- else if (state_r == CTRL_AUTO_REFRESH)
- auto_ref_r <= 1'b0;
- end
-
-
- // keep track of which chip selects got auto-refreshed (avoid auto-refreshing
- // all CS's at once to avoid current spike)
- always @(posedge clk)begin
- if (rst_r1 || (state_r1 == CTRL_PRECHARGE))
- auto_cnt_r <= 'd0;
- else if (state_r1 == CTRL_AUTO_REFRESH)
- auto_cnt_r <= auto_cnt_r + 1;
- end
-
- // register for timing purposes. Extra delay doesn't really matter
- always @(posedge clk)
- phy_init_done_r <= phy_init_done;
-
- always @(posedge clk)begin
- if (rst_r1) begin
- state_r <= CTRL_IDLE;
- state_r1 <= CTRL_IDLE;
- end else begin
- state_r <= next_state;
- state_r1 <= state_r;
- end
- end
-
- //***************************************************************************
- // main control state machine
- //***************************************************************************
-
- always @(*) begin
- next_state = state_r;
- (* full_case, parallel_case *) case (state_r)
- CTRL_IDLE: begin
- // perform auto refresh as soon as we are done with calibration.
- // The calibration logic does not do any refreshes.
- if (phy_init_done_r)
- next_state = CTRL_AUTO_REFRESH;
- end
-
- CTRL_PRECHARGE: begin
- if (auto_ref_r)
- next_state = CTRL_PRECHARGE_WAIT1;
- // when precharging an LRU bank, do not have to go to wait state
- // since we can't possibly be activating row in same bank next
- // disabled for 2t timing. There needs to be a gap between cmds
- // in 2t timing
- else if (no_precharge_wait_r && !TWO_T_TIME_EN)
- next_state = CTRL_ACTIVE;
- else
- next_state = CTRL_PRECHARGE_WAIT;
- end
-
- CTRL_PRECHARGE_WAIT:begin
- if (rp_cnt_ok_r)begin
- if (auto_ref_r)
- // precharge again to make sure we close all the banks
- next_state = CTRL_PRECHARGE;
- else
- next_state = CTRL_ACTIVE;
- end
- end
-
- CTRL_PRECHARGE_WAIT1:
- if (rp_cnt_ok_r)
- next_state = CTRL_AUTO_REFRESH;
-
- CTRL_AUTO_REFRESH:
- next_state = CTRL_AUTO_REFRESH_WAIT;
-
- CTRL_AUTO_REFRESH_WAIT:
- //staggering Auto refresh for multi
- // chip select designs. The SM waits
- // for the rfc time before issuing the
- // next auto refresh.
- if (auto_cnt_r < (CS_NUM))begin
- if (rfc_ok_r )
- next_state = CTRL_AUTO_REFRESH;
- end else if (rfc_ok_r)begin
- if(auto_ref_r)
- // MIG 2.3: For deep designs if Auto Refresh
- // flag asserted immediately after calibration is completed
- next_state = CTRL_PRECHARGE;
- else if ( wr_flag || rd_flag)
- next_state = CTRL_ACTIVE;
- end
-
- CTRL_ACTIVE:
- next_state = CTRL_ACTIVE_WAIT;
-
- CTRL_ACTIVE_WAIT: begin
- if (rcd_cnt_ok_r) begin
- if ((conflict_detect_r && ~conflict_resolved_r) ||
- auto_ref_r) begin
- if (no_precharge_r1 && ~auto_ref_r && trrd_cnt_ok_r)
- next_state = CTRL_ACTIVE;
- else if(precharge_ok_r)
- next_state = CTRL_PRECHARGE;
- end else if ((wr_flag_r) && (rd_to_wr_ok_r))
- next_state = CTRL_BURST_WRITE;
- else if ((rd_flag_r)&& (wr_to_rd_ok_r))
- next_state = CTRL_BURST_READ;
- end
- end
-
- // beginning of write burst
- CTRL_BURST_WRITE: begin
- if (BURST_LEN_DIV2 == 1) begin
- // special case if BL = 2 (i.e. burst lasts only one clk cycle)
- if (wr_flag)
- // if we have another non-conflict write command right after the
- // current write, then stay in this state
- next_state = CTRL_BURST_WRITE;
- else
- // otherwise, if we're done with this burst, and have no write
- // immediately scheduled after this one, wait until write-read
- // delay has passed
- next_state = CTRL_WRITE_WAIT;
- end else
- // otherwise BL > 2, and we have at least one more write cycle for
- // current burst
- next_state = CTRL_WRITE_WAIT;
- // continuation of write burst (also covers waiting after write burst
- // has completed for write-read delay to pass)
- end
-
- CTRL_WRITE_WAIT: begin
- if ((conflict_detect) || auto_ref_r) begin
- if (no_precharge_r && ~auto_ref_r && wrburst_ok_r)
- next_state = CTRL_ACTIVE;
- else if (precharge_ok_r)
- next_state = CTRL_PRECHARGE;
- end else if (wrburst_ok_r && wr_flag)
- next_state = CTRL_BURST_WRITE;
- else if ((rd_flag) && (wr_to_rd_ok_r))
- next_state = CTRL_BURST_READ;
- end
-
- CTRL_BURST_READ: begin
- if (BURST_LEN_DIV2 == 1) begin
- // special case if BL = 2 (i.e. burst lasts only one clk cycle)
- if (rd_flag)
- next_state = CTRL_BURST_READ;
- else
- next_state = CTRL_READ_WAIT;
- end else
- next_state = CTRL_READ_WAIT;
- end
-
- CTRL_READ_WAIT: begin
- if ((conflict_detect) || auto_ref_r)begin
- if (no_precharge_r && ~auto_ref_r && rdburst_ok_r)
- next_state = CTRL_ACTIVE;
- else if (precharge_ok_r)
- next_state = CTRL_PRECHARGE;
- // for burst of 4 in multi chip select
- // if there is a change in cs wait one cycle before the
- // next read command. cs_change_r will be asserted.
- end else if (rdburst_ok_r && rd_flag && ~cs_change_r)
- next_state = CTRL_BURST_READ;
- else if (wr_flag && (rd_to_wr_ok_r))
- next_state = CTRL_BURST_WRITE;
- end
- endcase
- end
-
- //***************************************************************************
- // control signals to memory
- //***************************************************************************
-
- always @(posedge clk) begin
- if ((state_r == CTRL_AUTO_REFRESH) ||
- (state_r == CTRL_ACTIVE) ||
- (state_r == CTRL_PRECHARGE)) begin
- ddr_ras_n_r <= 1'b0;
- two_t_enable_r[0] <= 1'b0;
- end else begin
- if (TWO_T_TIME_EN)
- ddr_ras_n_r <= two_t_enable_r[0] ;
- else
- ddr_ras_n_r <= 1'd1;
- two_t_enable_r[0] <= 1'b1;
- end
- end
-
- always @(posedge clk)begin
- if ((state_r == CTRL_BURST_WRITE) ||
- (state_r == CTRL_BURST_READ) ||
- (state_r == CTRL_AUTO_REFRESH)) begin
- ddr_cas_n_r <= 1'b0;
- two_t_enable_r[1] <= 1'b0;
- end else begin
- if (TWO_T_TIME_EN)
- ddr_cas_n_r <= two_t_enable_r[1];
- else
- ddr_cas_n_r <= 1'b1;
- two_t_enable_r[1] <= 1'b1;
- end
- end
-
- always @(posedge clk) begin
- if ((state_r == CTRL_BURST_WRITE) ||
- (state_r == CTRL_PRECHARGE)) begin
- ddr_we_n_r <= 1'b0;
- two_t_enable_r[2] <= 1'b0;
- end else begin
- if(TWO_T_TIME_EN)
- ddr_we_n_r <= two_t_enable_r[2];
- else
- ddr_we_n_r <= 1'b1;
- two_t_enable_r[2] <= 1'b1;
- end
- end
-
- // turn off auto-precharge when issuing commands (A10 = 0)
- // mapping the col add for linear addressing.
- generate
- if (TWO_T_TIME_EN) begin: gen_addr_col_two_t
- if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0
- assign ddr_addr_col = {af_addr_r3[COL_WIDTH-1:10], 1'b0,
- af_addr_r3[9:0]};
- end else begin
- if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1
- assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
- af_addr_r3[COL_WIDTH-1:10], 1'b0,
- af_addr_r3[9:0]};
- end else begin: gen_ddr_addr_col_2
- assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
- af_addr_r3[COL_WIDTH-1:0]};
- end
- end
- end else begin: gen_addr_col_one_t
- if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0_1
- assign ddr_addr_col = {af_addr_r2[COL_WIDTH-1:10], 1'b0,
- af_addr_r2[9:0]};
- end else begin
- if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1_1
- assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
- af_addr_r2[COL_WIDTH-1:10], 1'b0,
- af_addr_r2[9:0]};
- end else begin: gen_ddr_addr_col_2_1
- assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
- af_addr_r2[COL_WIDTH-1:0]};
- end
- end
- end
- endgenerate
-
- // Assign address during row activate
- generate
- if (TWO_T_TIME_EN)
- assign ddr_addr_row = af_addr_r3[ROW_RANGE_END:ROW_RANGE_START];
- else
- assign ddr_addr_row = af_addr_r2[ROW_RANGE_END:ROW_RANGE_START];
- endgenerate
-
-
- always @(posedge clk)begin
- if ((state_r == CTRL_ACTIVE) ||
- ((state_r1 == CTRL_ACTIVE) && TWO_T_TIME_EN))
- ddr_addr_r <= ddr_addr_row;
- else if ((state_r == CTRL_BURST_WRITE) ||
- (state_r == CTRL_BURST_READ) ||
- (((state_r1 == CTRL_BURST_WRITE) ||
- (state_r1 == CTRL_BURST_READ)) &&
- TWO_T_TIME_EN))
- ddr_addr_r <= ddr_addr_col;
- else if (((state_r == CTRL_PRECHARGE) ||
- ((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
- && auto_ref_r) begin
- // if we're precharging as a result of AUTO-REFRESH, precharge all banks
- ddr_addr_r <= {ROW_WIDTH{1'b0}};
- ddr_addr_r[10] <= 1'b1;
- end else if ((state_r == CTRL_PRECHARGE) ||
- ((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
- // if we're precharging to close a specific bank/row, set A10=0
- ddr_addr_r <= {ROW_WIDTH{1'b0}};
- else
- ddr_addr_r <= {ROW_WIDTH{1'bx}};
- end
-
- always @(posedge clk)begin
- // whenever we're precharging, we're either: (1) precharging all banks (in
- // which case banks bits are don't care, (2) precharging the LRU bank,
- // b/c we've exceeded the limit of # of banks open (need to close the LRU
- // bank to make room for a new one), (3) we haven't exceed the maximum #
- // of banks open, but we trying to open a different row in a bank that's
- // already open
- if (((state_r == CTRL_PRECHARGE) ||
- ((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN)) &&
- bank_conflict_r && MULTI_BANK_EN)
- // When LRU bank needs to be closed
- ddr_ba_r <= bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_BANK_RANGE_END:
- (3*CMP_WIDTH)+CMP_BANK_RANGE_START];
- else begin
- // Either precharge due to refresh or bank hit case
- if (TWO_T_TIME_EN)
- ddr_ba_r <= af_addr_r3[BANK_RANGE_END:BANK_RANGE_START];
- else
- ddr_ba_r <= af_addr_r2[BANK_RANGE_END:BANK_RANGE_START];
- end
- end
-
- // chip enable generation logic
- generate
- // if only one chip select, always assert it after reset
- if (CS_BITS == 0) begin: gen_ddr_cs_0
- always @(posedge clk)
- if (rst_r1)
- ddr_cs_n_r[0] <= 1'b1;
- else
- ddr_cs_n_r[0] <= 1'b0;
- // otherwise if we have multiple chip selects
- end else begin: gen_ddr_cs_1
- if(TWO_T_TIME_EN) begin: gen_2t_cs
- always @(posedge clk)
- if (rst_r1)
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- else if ((state_r1 == CTRL_AUTO_REFRESH)) begin
- // if auto-refreshing, only auto-refresh one CS at any time (avoid
- // beating on the ground plane by refreshing all CS's at same time)
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- ddr_cs_n_r[auto_cnt_r] <= 1'b0;
- end else if (auto_ref_r && (state_r1 == CTRL_PRECHARGE)) begin
- ddr_cs_n_r <= {CS_NUM{1'b0}};
- end else if ((state_r1 == CTRL_PRECHARGE) && ( bank_conflict_r
- && MULTI_BANK_EN))begin
- // precharging the LRU bank
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
- (3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
- end else begin
- // otherwise, check the upper address bits to see which CS to assert
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- ddr_cs_n_r[af_addr_r3[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
- end // else: !if(((state_r == CTRL_PRECHARGE) ||...
- end else begin: gen_1t_cs // block: gen_2t_cs
- always @(posedge clk)
- if (rst_r1)
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- else if ((state_r == CTRL_AUTO_REFRESH) ) begin
- // if auto-refreshing, only auto-refresh one CS at any time (avoid
- // beating on the ground plane by refreshing all CS's at same time)
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- ddr_cs_n_r[auto_cnt_r] <= 1'b0;
- end else if (auto_ref_r && (state_r == CTRL_PRECHARGE) ) begin
- ddr_cs_n_r <= {CS_NUM{1'b0}};
- end else if ((state_r == CTRL_PRECHARGE) &&
- (bank_conflict_r && MULTI_BANK_EN))begin
- // precharging the LRU bank
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
- (3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
- end else begin
- // otherwise, check the upper address bits to see which CS to assert
- ddr_cs_n_r <= {CS_NUM{1'b1}};
- ddr_cs_n_r[af_addr_r2[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
- end // else: !if(((state_r == CTRL_PRECHARGE) ||...
- end // block: gen_1t_cs
- end
- endgenerate
-
- // registring the two_t timing enable signal.
- // This signal will be asserted (low) when the
- // chip select has to be asserted.
- always @(posedge clk)begin
- if(&two_t_enable_r)
- two_t_enable_r1 <= {CS_NUM{1'b1}};
- else
- two_t_enable_r1 <= {CS_NUM{1'b0}};
- end
-
- assign ctrl_addr = ddr_addr_r;
- assign ctrl_ba = ddr_ba_r;
- assign ctrl_ras_n = ddr_ras_n_r;
- assign ctrl_cas_n = ddr_cas_n_r;
- assign ctrl_we_n = ddr_we_n_r;
- assign ctrl_cs_n = (TWO_T_TIME_EN) ?
- (ddr_cs_n_r | two_t_enable_r1) :
- ddr_cs_n_r;
-
-endmodule
-
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_addr_fifo.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_addr_fifo.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_usr_addr_fifo.v (nonexistent)
@@ -1,131 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_usr_addr_fifo.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Mon Aug 28 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module instantiates the block RAM based FIFO to store the user
-// address and the command information. Also calculates potential bank/row
-// conflicts by comparing the new address with last address issued.
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_usr_addr_fifo #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter COL_WIDTH = 10,
- parameter CS_BITS = 0,
- parameter ROW_WIDTH = 14
- )
- (
- input clk0,
- input rst0,
- input [2:0] app_af_cmd,
- input [30:0] app_af_addr,
- input app_af_wren,
- input ctrl_af_rden,
- output [2:0] af_cmd,
- output [30:0] af_addr,
- output af_empty,
- output app_af_afull
- );
-
- wire [35:0] fifo_data_out;
- reg rst_r;
-
-
- always @(posedge clk0)
- rst_r <= rst0;
-
-
- //***************************************************************************
-
- assign af_cmd = fifo_data_out[33:31];
- assign af_addr = fifo_data_out[30:0];
-
- //***************************************************************************
-
- FIFO36 #
- (
- .ALMOST_EMPTY_OFFSET (13'h0007),
- .ALMOST_FULL_OFFSET (13'h000F),
- .DATA_WIDTH (36),
- .DO_REG (1),
- .EN_SYN ("TRUE"),
- .FIRST_WORD_FALL_THROUGH ("FALSE")
- )
- u_af
- (
- .ALMOSTEMPTY (),
- .ALMOSTFULL (app_af_afull),
- .DO (fifo_data_out[31:0]),
- .DOP (fifo_data_out[35:32]),
- .EMPTY (af_empty),
- .FULL (),
- .RDCOUNT (),
- .RDERR (),
- .WRCOUNT (),
- .WRERR (),
- .DI ({app_af_cmd[0],app_af_addr}),
- .DIP ({2'b00,app_af_cmd[2:1]}),
- .RDCLK (clk0),
- .RDEN (ctrl_af_rden),
- .RST (rst_r),
- .WRCLK (clk0),
- .WREN (app_af_wren)
- );
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_dm_iob.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_dm_iob.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_dm_iob.v (nonexistent)
@@ -1,106 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_phy_dm_iob.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Wed Aug 16 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module places the data mask signals into the IOBs.
-//Reference:
-//Revision History:
-// Rev 1.1 - To fix timing issues with Synplicity 9.6.1, syn_preserve
-// attribute added for the instance u_dm_ce. PK. 11/11/08
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_phy_dm_iob
- (
- input clk90,
- input dm_ce,
- input mask_data_rise,
- input mask_data_fall,
- output ddr_dm
- );
-
- wire dm_out;
- wire dm_ce_r;
-
- FDRSE_1 u_dm_ce
- (
- .Q (dm_ce_r),
- .C (clk90),
- .CE (1'b1),
- .D (dm_ce),
- .R (1'b0),
- .S (1'b0)
- ) /* synthesis syn_preserve=1 */;
-
- ODDR #
- (
- .SRTYPE("SYNC"),
- .DDR_CLK_EDGE("SAME_EDGE")
- )
- u_oddr_dm
- (
- .Q (dm_out),
- .C (clk90),
- .CE (dm_ce_r),
- .D1 (mask_data_rise),
- .D2 (mask_data_fall),
- .R (1'b0),
- .S (1'b0)
- );
-
- OBUF u_obuf_dm
- (
- .I (dm_out),
- .O (ddr_dm)
- );
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_write.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_write.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl/ddr2_phy_write.v (nonexistent)
@@ -1,469 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_phy_write.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Thu Aug 24 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-//Reference:
-// Handles delaying various write control signals appropriately depending
-// on CAS latency, additive latency, etc. Also splits the data and mask in
-// rise and fall buses.
-//Revision History:
-// Rev 1.1 - For Dual Rank parts support ODT logic corrected. PK. 08/05/08
-// Rev 1.2 - Retain current data pattern for stage 4 calibration, and create
-// new pattern for stage 4. RC. 09/21/09.
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_phy_write #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter DQ_WIDTH = 72,
- parameter CS_NUM = 1,
- parameter ADDITIVE_LAT = 0,
- parameter CAS_LAT = 5,
- parameter ECC_ENABLE = 0,
- parameter ODT_TYPE = 1,
- parameter REG_ENABLE = 1,
- parameter DDR_TYPE = 1
- )
- (
- input clk0,
- input clk90,
- input rst90,
- input [(2*DQ_WIDTH)-1:0] wdf_data,
- input [(2*DQ_WIDTH/8)-1:0] wdf_mask_data,
- input ctrl_wren,
- input phy_init_wren,
- input phy_init_data_sel,
- output reg dm_ce,
- output reg [1:0] dq_oe_n,
- output reg dqs_oe_n ,
- output reg dqs_rst_n ,
- output wdf_rden,
- output reg [CS_NUM-1:0] odt ,
- output [DQ_WIDTH-1:0] wr_data_rise,
- output [DQ_WIDTH-1:0] wr_data_fall,
- output [(DQ_WIDTH/8)-1:0] mask_data_rise,
- output [(DQ_WIDTH/8)-1:0] mask_data_fall
- );
-
- localparam MASK_WIDTH = DQ_WIDTH/8;
- localparam DDR1 = 0;
- localparam DDR2 = 1;
- localparam DDR3 = 2;
-
- // (MIN,MAX) value of WR_LATENCY for DDR1:
- // REG_ENABLE = (0,1)
- // ECC_ENABLE = (0,1)
- // Write latency = 1
- // Total: (1,3)
- // (MIN,MAX) value of WR_LATENCY for DDR2:
- // REG_ENABLE = (0,1)
- // ECC_ENABLE = (0,1)
- // Write latency = ADDITIVE_CAS + CAS_LAT - 1 = (0,4) + (3,5) - 1 = (2,8)
- // ADDITIVE_LAT = (0,4) (JEDEC79-2B)
- // CAS_LAT = (3,5) (JEDEC79-2B)
- // Total: (2,10)
- localparam WR_LATENCY = (DDR_TYPE == DDR3) ?
- (ADDITIVE_LAT + (CAS_LAT) + REG_ENABLE ) :
- (DDR_TYPE == DDR2) ?
- (ADDITIVE_LAT + (CAS_LAT-1) + REG_ENABLE ) :
- (1 + REG_ENABLE );
-
- // NOTE that ODT timing does not need to be delayed for registered
- // DIMM case, since like other control/address signals, it gets
- // delayed by one clock cycle at the DIMM
- localparam ODT_WR_LATENCY = WR_LATENCY - REG_ENABLE;
-
- wire dm_ce_0;
- reg dm_ce_r;
- wire [1:0] dq_oe_0;
- reg [1:0] dq_oe_n_90_r1;
- reg [1:0] dq_oe_270;
- wire dqs_oe_0;
- reg dqs_oe_270;
- reg dqs_oe_n_180_r1;
- wire dqs_rst_0;
- reg dqs_rst_n_180_r1;
- reg dqs_rst_270;
- reg ecc_dm_error_r;
- reg ecc_dm_error_r1;
- reg [(DQ_WIDTH-1):0] init_data_f;
- reg [(DQ_WIDTH-1):0] init_data_r;
- reg [3:0] init_wdf_cnt_r;
- wire odt_0;
- reg rst90_r /* synthesis syn_maxfan = 10 */;
- reg [10:0] wr_stages ;
- reg [(2*DQ_WIDTH)-1:0] wdf_data_r;
- reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r;
- wire [(2*DQ_WIDTH/8)-1:0] wdf_ecc_mask;
-
- reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r1;
- wire wdf_rden_0;
- reg calib_rden_90_r;
- reg wdf_rden_90_r;
- reg wdf_rden_90_r1;
- reg wdf_rden_270;
-
- always @(posedge clk90)
- rst90_r <= rst90;
-
- //***************************************************************************
- // Analysis of additional pipeline delays:
- // 1. dq_oe (DQ 3-state): 1 CLK90 cyc in IOB 3-state FF
- // 2. dqs_oe (DQS 3-state): 1 CLK180 cyc in IOB 3-state FF
- // 3. dqs_rst (DQS output value reset): 1 CLK180 cyc in FF + 1 CLK180 cyc
- // in IOB DDR
- // 4. odt (ODT control): 1 CLK0 cyc in IOB FF
- // 5. write data (output two cyc after wdf_rden - output of RAMB_FIFO w/
- // output register enabled): 2 CLK90 cyc in OSERDES
- //***************************************************************************
-
- // DQS 3-state must be asserted one extra clock cycle due b/c of write
- // pre- and post-amble (extra half clock cycle for each)
- assign dqs_oe_0 = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
-
- // same goes for ODT, need to handle both pre- and post-amble (generate
- // ODT only for DDR2)
- // ODT generation for DDR2 based on write latency. The MIN write
- // latency is 2. Based on the write latency ODT is asserted.
- generate
- if ((DDR_TYPE != DDR1) && (ODT_TYPE > 0))begin: gen_odt_ddr2
- if(ODT_WR_LATENCY > 3)
- assign odt_0 =
- wr_stages[ODT_WR_LATENCY-2] |
- wr_stages[ODT_WR_LATENCY-3] |
- wr_stages[ODT_WR_LATENCY-4] ;
- else if ( ODT_WR_LATENCY == 3)
- assign odt_0 =
- wr_stages[ODT_WR_LATENCY-1] |
- wr_stages[ODT_WR_LATENCY-2] |
- wr_stages[ODT_WR_LATENCY-3] ;
- else
- assign odt_0 =
- wr_stages[ODT_WR_LATENCY] |
- wr_stages[ODT_WR_LATENCY-1] |
- wr_stages[ODT_WR_LATENCY-2] ;
- end else
- assign odt_0 = 1'b0;
- endgenerate
-
- assign dq_oe_0[0] = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY];
- assign dq_oe_0[1] = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
- assign dqs_rst_0 = ~wr_stages[WR_LATENCY-2];
- assign dm_ce_0 = wr_stages[WR_LATENCY] | wr_stages[WR_LATENCY-1]
- | wr_stages[WR_LATENCY-2];
-
- // write data fifo, read flag assertion
- generate
- if (DDR_TYPE != DDR1) begin: gen_wdf_ddr2
- if (WR_LATENCY > 2)
- assign wdf_rden_0 = wr_stages[WR_LATENCY-3];
- else
- assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
- end else begin: gen_wdf_ddr1
- assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
- end
- endgenerate
-
- // first stage isn't registered
- always @(*)
- wr_stages[0] = (phy_init_data_sel) ? ctrl_wren : phy_init_wren;
-
- always @(posedge clk0) begin
- wr_stages[1] <= wr_stages[0];
- wr_stages[2] <= wr_stages[1];
- wr_stages[3] <= wr_stages[2];
- wr_stages[4] <= wr_stages[3];
- wr_stages[5] <= wr_stages[4];
- wr_stages[6] <= wr_stages[5];
- wr_stages[7] <= wr_stages[6];
- wr_stages[8] <= wr_stages[7];
- wr_stages[9] <= wr_stages[8];
- wr_stages[10] <= wr_stages[9];
- end
-
- // intermediate synchronization to CLK270
- always @(negedge clk90) begin
- dq_oe_270 <= dq_oe_0;
- dqs_oe_270 <= dqs_oe_0;
- dqs_rst_270 <= dqs_rst_0;
- wdf_rden_270 <= wdf_rden_0;
- end
-
- // synchronize DQS signals to CLK180
- always @(negedge clk0) begin
- dqs_oe_n_180_r1 <= ~dqs_oe_270;
- dqs_rst_n_180_r1 <= ~dqs_rst_270;
- end
-
- // All write data-related signals synced to CLK90
- always @(posedge clk90) begin
- dq_oe_n_90_r1 <= ~dq_oe_270;
- wdf_rden_90_r <= wdf_rden_270;
- end
-
- // generate for wdf_rden and calib rden. These signals
- // are asserted based on write latency. For write
- // latency of 2, the extra register stage is taken out.
- generate
- if (WR_LATENCY > 2) begin
- always @(posedge clk90) begin
- // assert wdf rden only for non calibration opertations
- wdf_rden_90_r1 <= wdf_rden_90_r &
- phy_init_data_sel;
- // rden for calibration
- calib_rden_90_r <= wdf_rden_90_r;
- end
- end else begin
- always @(*) begin
- wdf_rden_90_r1 = wdf_rden_90_r
- & phy_init_data_sel;
- calib_rden_90_r = wdf_rden_90_r;
- end
- end // else: !if(WR_LATENCY > 2)
- endgenerate
-
- // dm CE signal to stop dm oscilation
- always @(negedge clk90)begin
- dm_ce_r <= dm_ce_0;
- dm_ce <= dm_ce_r;
- end
-
- // When in ECC mode the upper byte [71:64] will have the
- // ECC parity. Mapping the bytes which have valid data
- // to the upper byte in ecc mode. Also in ecc mode there
- // is an extra register stage to account for timing.
-
- genvar mask_i;
- generate
- if(ECC_ENABLE) begin
- for (mask_i = 0; mask_i < (2*DQ_WIDTH)/72;
- mask_i = mask_i+1) begin: gen_mask
- assign wdf_ecc_mask[((mask_i*9)+9)-1:(mask_i*9)] =
- {&wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9],
- wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9]};
- end
- end
- endgenerate
-
- generate
- if (ECC_ENABLE) begin:gen_ecc_reg
- always @(posedge clk90)begin
- if(phy_init_data_sel)
- wdf_mask_r <= wdf_ecc_mask;
- else
- wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
- end
- end else begin
- always@(posedge clk90) begin
- if (phy_init_data_sel)
- wdf_mask_r <= wdf_mask_data;
- else
- wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
- end
- end
- endgenerate
-
- always @(posedge clk90) begin
- if(phy_init_data_sel)
- wdf_data_r <= wdf_data;
- else
- wdf_data_r <={init_data_f,init_data_r};
- end
-
- // Error generation block during simulation.
- // Error will be displayed when all the DM
- // bits are not zero. The error will be
- // displayed only during the start of the sequence
- // for errors that are continous over many cycles.
- generate
- if (ECC_ENABLE) begin: gen_ecc_error
- always @(posedge clk90) begin
- //synthesis translate_off
- wdf_mask_r1 <= wdf_mask_r;
- if(DQ_WIDTH > 72)
- ecc_dm_error_r
- <= (
- (~wdf_mask_r1[35] && (|wdf_mask_r1[34:27])) ||
- (~wdf_mask_r1[26] && (|wdf_mask_r1[25:18])) ||
- (~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
- (~wdf_mask_r1[8] && (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
- else
- ecc_dm_error_r
- <= ((~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
- (~wdf_mask_r1[8] && (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
- ecc_dm_error_r1 <= ecc_dm_error_r ;
- if (ecc_dm_error_r && ~ecc_dm_error_r1) // assert the error only once.
- $display ("ECC DM ERROR. ");
- //synthesis translate_on
- end
- end
- endgenerate
-
- //***************************************************************************
- // State logic to write calibration training patterns
- //***************************************************************************
-
- always @(posedge clk90) begin
- if (rst90_r) begin
- init_wdf_cnt_r <= 4'd0;
- init_data_r <= {64{1'bx}};
- init_data_f <= {64{1'bx}};
- end else begin
- init_wdf_cnt_r <= init_wdf_cnt_r + calib_rden_90_r;
- casex (init_wdf_cnt_r)
- // First stage calibration. Pattern (rise/fall) = 1(r)->0(f)
- // The rise data and fall data are already interleaved in the manner
- // required for data into the WDF write FIFO
- 4'b00xx: begin
- init_data_r <= {DQ_WIDTH{1'b1}};
- init_data_f <= {DQ_WIDTH{1'b0}};
- end
- // Second stage calibration. Pattern = 1(r)->1(f)->0(r)->0(f)
- 4'b01x0: begin
- init_data_r <= {DQ_WIDTH{1'b1}};
- init_data_f <= {DQ_WIDTH{1'b1}};
- end
- 4'b01x1: begin
- init_data_r <= {DQ_WIDTH{1'b0}};
- init_data_f <= {DQ_WIDTH{1'b0}};
- end
- // MIG 3.2: Changed Stage 3/4 training pattern
- // Third stage calibration patern =
- // 11(r)->ee(f)->ee(r)->11(f)-ee(r)->11(f)->ee(r)->11(f)
- 4'b1000: begin
- init_data_r <= {DQ_WIDTH/4{4'h1}};
- init_data_f <= {DQ_WIDTH/4{4'hE}};
- end
- 4'b1001: begin
- init_data_r <= {DQ_WIDTH/4{4'hE}};
- init_data_f <= {DQ_WIDTH/4{4'h1}};
- end
- 4'b1010: begin
- init_data_r <= {(DQ_WIDTH/4){4'hE}};
- init_data_f <= {(DQ_WIDTH/4){4'h1}};
- end
- 4'b1011: begin
- init_data_r <= {(DQ_WIDTH/4){4'hE}};
- init_data_f <= {(DQ_WIDTH/4){4'h1}};
- end
- // Fourth stage calibration patern =
- // 11(r)->ee(f)->ee(r)->11(f)-11(r)->ee(f)->ee(r)->11(f)
- 4'b1100: begin
- init_data_r <= {DQ_WIDTH/4{4'h1}};
- init_data_f <= {DQ_WIDTH/4{4'hE}};
- end
- 4'b1101: begin
- init_data_r <= {DQ_WIDTH/4{4'hE}};
- init_data_f <= {DQ_WIDTH/4{4'h1}};
- end
- 4'b1110: begin
- init_data_r <= {(DQ_WIDTH/4){4'h1}};
- init_data_f <= {(DQ_WIDTH/4){4'hE}};
- end
- 4'b1111: begin
- // MIG 3.5: Corrected last two writes for stage 4 calibration
- // training pattern. Previously MIG 3.3 and MIG 3.4 had the
- // incorrect pattern. This can sometimes result in a calibration
- // point with small timing margin.
-// init_data_r <= {(DQ_WIDTH/4){4'h1}};
-// init_data_f <= {(DQ_WIDTH/4){4'hE}};
- init_data_r <= {(DQ_WIDTH/4){4'hE}};
- init_data_f <= {(DQ_WIDTH/4){4'h1}};
- end
- endcase
- end
- end
-
- //***************************************************************************
-
- always @(posedge clk90)
- dq_oe_n <= dq_oe_n_90_r1;
-
- always @(negedge clk0)
- dqs_oe_n <= dqs_oe_n_180_r1;
-
- always @(negedge clk0)
- dqs_rst_n <= dqs_rst_n_180_r1;
-
- // generate for odt. odt is asserted based on
- // write latency. For write latency of 2
- // the extra register stage is taken out.
- generate
- if (ODT_WR_LATENCY > 3) begin
- always @(posedge clk0) begin
- odt <= 'b0;
- odt[0] <= odt_0;
- end
- end else begin
- always @ (*) begin
- odt = 'b0;
- odt[0] = odt_0;
- end
- end
- endgenerate
-
- assign wdf_rden = wdf_rden_90_r1;
-
- //***************************************************************************
- // Format write data/mask: Data is in format: {fall, rise}
- //***************************************************************************
-
- assign wr_data_rise = wdf_data_r[DQ_WIDTH-1:0];
- assign wr_data_fall = wdf_data_r[(2*DQ_WIDTH)-1:DQ_WIDTH];
- assign mask_data_rise = wdf_mask_r[MASK_WIDTH-1:0];
- assign mask_data_fall = wdf_mask_r[(2*MASK_WIDTH)-1:MASK_WIDTH];
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/rtl
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/rtl (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/rtl (nonexistent)
rtl/XilinxMIG_MemCtrl/user_design/rtl
Property changes :
Deleted: bugtraq:number
## -1 +0,0 ##
-true
\ No newline at end of property
Index: rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_gen.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_gen.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_gen.v (nonexistent)
@@ -1,159 +0,0 @@
-//*****************************************************************************
-// Company: UPT
-// Engineer: Oana Boncalo & Alexandru Amaricai
-//
-// Create Date: 10:23:39 11/26/2012
-// Design Name:
-// Module Name: DDR2 user IF address and data generation
-// Project Name:
-// Target Devices:
-// Tool versions:
-//Device: Virtex-5
-//Purpose:
-// This module instantiates the addr_gen and the data_gen modules. It takes
-// the user data stored in internal FIFOs and gives the data that is to be
-// compared with the read data
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_adr_data_gen #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter COL_WIDTH = 10,
- parameter DM_WIDTH = 9,
- parameter DQ_WIDTH = 72,
- parameter APPDATA_WIDTH = 144,
- parameter ECC_ENABLE = 0,
- parameter ROW_WIDTH = 14
- )
- (
- input clk,
- input rst,
- input wr_addr_en,
- input wr_data_en,
- input rd_op,
- input rd_data_valid,
- input [30:0] bus_if_addr,
- input [APPDATA_WIDTH-1:0] bus_if_wr_data,
- input [(APPDATA_WIDTH/8)-1:0] bus_if_wr_mask_data,
- output reg app_af_wren,
- output [2:0] app_af_cmd,
- output [30:0] app_af_addr,
- output app_wdf_wren,
- output [APPDATA_WIDTH-1:0] app_wdf_data,
- output [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data
- );
-
- //data
- localparam RD_IDLE_FIRST_DATA = 2'b00;
- localparam RD_SECOND_DATA = 2'b01;
- localparam RD_THIRD_DATA = 2'b10;
- localparam RD_FOURTH_DATA = 2'b11;
-
- //address
- reg wr_addr_en_r1;
- reg [2:0] af_cmd_r;//, af_cmd_r0, af_cmd_r1;
- reg af_wren_r;
- reg rst_r
- /* synthesis syn_preserve = 1 */;
- reg rst_r1
- /* synthesis syn_maxfan = 10 */;
- reg [5:0] wr_addr_r;
- reg wr_addr_en_r0;
-
- //data
- reg [APPDATA_WIDTH-1:0] app_wdf_data_r;
- reg [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data_r;
- wire app_wdf_wren_r;
- reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_fall;
- reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_rise;
- reg [1:0] rd_state;
- wire [APPDATA_WIDTH-1:0] wr_data;
- reg wr_data_en_r;
- reg [(APPDATA_WIDTH/2)-1:0] wr_data_fall
- /* synthesis syn_maxfan = 2 */;
- reg [(APPDATA_WIDTH/2)-1:0] wr_data_rise
- /* synthesis syn_maxfan = 2 */;
- wire [(APPDATA_WIDTH/8)-1:0] wr_mask_data;
-
- //***************************************************************************
-
- // local reset "tree" for controller logic only. Create this to ease timing
- // on reset path. Prohibit equivalent register removal on RST_R to prevent
- // "sharing" with other local reset trees (caution: make sure global fanout
- // limit is set to larger than fanout on RST_R, otherwise SLICES will be
- // used for fanout control on RST_R.
- always @(posedge clk) begin
- rst_r <= rst;
- rst_r1 <= rst_r;
- end
-// register backend enables / FIFO enables
- // write enable for Command/Address FIFO is generated 1 CC after WR_ADDR_EN
- always @(posedge clk)
- if (rst_r1) begin
- app_af_wren <= 1'b0;
- end else begin
- app_af_wren <= wr_addr_en;
- end
-
- always @ (posedge clk)
- if (rst_r1)
- wr_addr_r <= 0;
- else if (wr_addr_en && (rd_op == 1'b0))
- wr_addr_r <= bus_if_addr;
-
- assign app_af_addr = wr_addr_r;
- assign app_af_cmd = af_cmd_r;
-
- always @ (posedge clk)
- begin
- af_cmd_r <= 0;
- if (rd_op)
- af_cmd_r <= 3'b001;
- end
-
-
- //data
- assign app_wdf_data = wr_data;
- assign app_wdf_mask_data = wr_mask_data;
- // inst ff for timing
- FDRSE ff_wdf_wren
- (
- .Q (app_wdf_wren),
- .C (clk),
- .CE (1'b1),
- .D (wr_data_en),
- .R (1'b0),
- .S (1'b0)
- );
-
- assign wr_data = {wr_data_fall, wr_data_rise};
- assign wr_mask_data = bus_if_wr_mask_data;
-
- //data latching
- //synthesis attribute max_fanout of wr_data_fall is 2
- //synthesis attribute max_fanout of wr_data_rise is 2
- always @(posedge clk)
- begin
- if (rst_r1)
- begin
- wr_data_rise <= {(APPDATA_WIDTH/2){1'bx}};
- wr_data_fall <= {(APPDATA_WIDTH/2){1'bx}};
- end
- else
- if (wr_data_en)
- begin
- wr_data_rise <= bus_if_wr_data[(APPDATA_WIDTH/2)-1:0];
- wr_data_fall <= bus_if_wr_data[APPDATA_WIDTH-1:(APPDATA_WIDTH/2)];
- end
- end
-
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_user_if_top.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_user_if_top.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_user_if_top.v (nonexistent)
@@ -1,211 +0,0 @@
-//*****************************************************************************
-// Company: UPT
-// Engineer: Oana Boncalo & Alexandru Amaricai
-//
-// Create Date: 10:23:39 11/26/2012
-// Design Name:
-// Module Name: DDR2 user IF for Genesys board
-// Project Name:
-// Target Devices:
-// Tool versions:
-//Device: Virtex-5
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_user_if_top #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter COL_WIDTH = 10,
- parameter DM_WIDTH = 9,
- parameter DQ_WIDTH = 72,
- parameter ROW_WIDTH = 14,
- parameter APPDATA_WIDTH = 144,
- parameter ECC_ENABLE = 0,
- parameter BURST_LEN = 4
- )
- (
- input clk0,
- input rst0,
- input app_af_afull,
- input app_wdf_afull,
- input rd_data_valid,
- input [APPDATA_WIDTH-1:0] rd_data_fifo_out,
- input phy_init_done,
- input rd_cmd,
- input wr_cmd,
- input [30:0] bus_if_addr,
- input [APPDATA_WIDTH-1:0] bus_if_wr_data,
- input [(APPDATA_WIDTH/8)-1:0] bus_if_wr_mask_data,
- output end_op,
- output req_wd,
- output app_af_wren,
- output [2:0] app_af_cmd,
- output [30:0] app_af_addr,
- output app_wdf_wren,
- output [APPDATA_WIDTH-1:0] app_wdf_data,
- output [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
- output error,
- output error_cmp
- );
-
- localparam BURST_LEN_DIV2 = BURST_LEN/2;
-
- localparam IDLE_CMD = 3'b000;
- localparam WRITE_CMD = 3'b001;
- localparam READ_CMD = 3'b010;
-
- reg app_af_not_afull_r;
- wire [APPDATA_WIDTH-1:0] app_cmp_data;
- reg app_wdf_not_afull_r ;
- reg [2:0] burst_cnt;
- reg phy_init_done_tb_r;
- wire phy_init_done_r;
- reg rst_r
- /* synthesis syn_preserve = 1 */;
- reg rst_r1
- /* synthesis syn_maxfan = 10 */;
- reg [2:0] state;
- reg [3:0] state_cnt;
- reg wr_addr_en ;
- reg wr_data_en ;
- reg rd_op;
- reg end_op_r;
-
- // XST attributes for local reset "tree"
- // synthesis attribute shreg_extract of rst_r is "no";
- // synthesis attribute shreg_extract of rst_r1 is "no";
- // synthesis attribute equivalent_register_removal of rst_r is "no"
-
- //*****************************************************************
-
- // local reset "tree" for controller logic only. Create this to ease timing
- // on reset path. Prohibit equivalent register removal on RST_R to prevent
- // "sharing" with other local reset trees (caution: make sure global fanout
- // limit is set to larger than fanout on RST_R, otherwise SLICES will be
- // used for fanout control on RST_R.
- always @(posedge clk0) begin
- rst_r <= rst0;
- rst_r1 <= rst_r;
- end
-
- // Instantiate flops for timing.
- FDRSE ff_phy_init_done
- (
- .Q (phy_init_done_r),
- .C (clk0),
- .CE (1'b1),
- .D (phy_init_done),
- .R (1'b0),
- .S (1'b0)
- );
-
- assign end_op = end_op_r;
- //***************************************************************************
- // State Machine for writing to WRITE DATA & ADDRESS FIFOs
- // state machine changed for low FIFO threshold values
- //***************************************************************************
-
- always @(posedge clk0) begin
- if (rst_r1) begin
- wr_data_en <= 1'bx;
- wr_addr_en <= 1'bx;
- state[2:0] <= IDLE_CMD;
- state_cnt <= 4'bxxxx;
- app_af_not_afull_r <= 1'bx;
- app_wdf_not_afull_r <= 1'bx;
- burst_cnt <= 3'bxxx;
- phy_init_done_tb_r <= 1'bx;
- rd_op <= 1'bx;
- end_op_r <= 1'bx;
- end else begin
- wr_data_en <= 1'b0;
- wr_addr_en <= 1'b0;
- rd_op <= 1'b0;
- end_op_r <= 1'b0;
- app_af_not_afull_r <= ~app_af_afull;
- app_wdf_not_afull_r <= ~app_wdf_afull;
- phy_init_done_tb_r <= phy_init_done_r;
-
- case (state)
- IDLE_CMD: begin
- state_cnt <= 4'd0;
- burst_cnt <= BURST_LEN_DIV2 - 1;
- end_op_r <= 1'b0;
- // only start writing when initialization done
- if (app_wdf_not_afull_r && app_af_not_afull_r && phy_init_done_tb_r)
- begin
- if (rd_cmd)
- state <= READ_CMD;
- if (wr_cmd)
- state <= WRITE_CMD;
- end
- end
-
- WRITE_CMD:
- if (app_wdf_not_afull_r && app_af_not_afull_r)
- begin
- wr_data_en <= 1'b1;
- // When we're done with the current burst...
- if (burst_cnt == 3'd0)
- begin
- wr_addr_en <= 1'b1;
- state <= IDLE_CMD;
- end_op_r <= 1'b1;
- end
- else
- burst_cnt <= burst_cnt - 1;
- end
-
- READ_CMD: begin
- burst_cnt <= BURST_LEN_DIV2 - 1;
- if (app_af_not_afull_r)
- begin
- wr_addr_en <= 1'b1;
- rd_op <= 1'b1;
- state <= IDLE_CMD;
- end_op_r <= 1'b1;
- end
- end
- endcase
- end
- end
- assign req_wd = (!wr_addr_en && wr_data_en)? 1'b1:1'b0;
-
- // Command/Address and Write Data generation
- ddr2_adr_data_gen #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .DM_WIDTH (DM_WIDTH),
- .DQ_WIDTH (DQ_WIDTH),
- .APPDATA_WIDTH (APPDATA_WIDTH),
- .ECC_ENABLE (ECC_ENABLE),
- .ROW_WIDTH (ROW_WIDTH)
- )
- u_adr_data_gen
- (
- .clk (clk0),
- .rst (rst0),
- .wr_addr_en (wr_addr_en),
- .wr_data_en (wr_data_en),
- .rd_op (rd_op),
- .rd_data_valid (rd_data_valid),
- .bus_if_addr (bus_if_addr),
- .app_af_wren (app_af_wren),
- .bus_if_wr_mask_data(bus_if_wr_mask_data),
- .bus_if_wr_data (bus_if_wr_data),
- .app_af_cmd (app_af_cmd),
- .app_af_addr (app_af_addr),
- .app_wdf_wren (app_wdf_wren),
- .app_wdf_data (app_wdf_data),
- .app_wdf_mask_data (app_wdf_mask_data)
- );
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_cmp.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_cmp.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_cmp.v (nonexistent)
@@ -1,266 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_tb_test_cmp.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Fri Sep 01 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module generates the error signal in case of bit errors. It compares
-// the read data with expected data value.
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_tb_test_cmp #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter DQ_WIDTH = 72,
- parameter APPDATA_WIDTH = 144,
- parameter ECC_ENABLE = 0
- )
- (
- input clk,
- input rst,
- input phy_init_done,
- input rd_data_valid,
- input [APPDATA_WIDTH-1:0] app_cmp_data,
- input [APPDATA_WIDTH-1:0] rd_data_fifo_in,
- output reg error,
- output reg error_cmp
- );
-
- wire [(APPDATA_WIDTH/16)-1:0] byte_err_fall;
- reg [(APPDATA_WIDTH/16)-1:0] byte_err_fall_r;
- wire [(APPDATA_WIDTH/16)-1:0] byte_err_rise;
- reg [(APPDATA_WIDTH/16)-1:0] byte_err_rise_r;
- wire [(APPDATA_WIDTH/2)-1:0] cmp_data_fall;
- wire [(APPDATA_WIDTH/2)-1:0] cmp_data_rise;
- wire [APPDATA_WIDTH-1:0] cmp_data_r;
- reg [APPDATA_WIDTH-1:0] cmp_data_r1;
- reg cmp_start;
- wire [(APPDATA_WIDTH/2)-1:0] data_fall_r;
- wire [(APPDATA_WIDTH/2)-1:0] data_rise_r;
- reg err_fall;
- reg err_rise;
- reg error_tmp_r;
- wire error_tmp_r1;
- wire error_tmp_r2;
- wire [APPDATA_WIDTH-1:0] rd_data_r;
- wire [APPDATA_WIDTH-1:0] rd_data_r1;
- reg [APPDATA_WIDTH-1:0] rd_data_r2;
- wire rd_data_valid_r;
- reg rd_data_valid_r1;
- reg rd_data_valid_r2;
- reg rst_r
- /* synthesis syn_preserve = 1 */;
- reg rst_r1
- /* synthesis syn_maxfan = 10 */;
-
- // XST attributes for local reset "tree"
- // synthesis attribute shreg_extract of rst_r is "no";
- // synthesis attribute shreg_extract of rst_r1 is "no";
- // synthesis attribute equivalent_register_removal of rst_r is "no"
-
- //***************************************************************************
-
- // local reset "tree" for controller logic only. Create this to ease timing
- // on reset path. Prohibit equivalent register removal on RST_R to prevent
- // "sharing" with other local reset trees (caution: make sure global fanout
- // limit is set to larger than fanout on RST_R, otherwise SLICES will be
- // used for fanout control on RST_R.
- always @(posedge clk) begin
- rst_r <= rst;
- rst_r1 <= rst_r;
- end
-
- // instantiate discrete flops for better timing
- genvar rd_data_i;
- generate
- for (rd_data_i = 0; rd_data_i < APPDATA_WIDTH;
- rd_data_i = rd_data_i + 1) begin: gen_rd_data
- FDRSE ff_rd_data
- (
- .Q (rd_data_r[rd_data_i]),
- .C (clk),
- .CE (1'b1),
- .D (rd_data_fifo_in[rd_data_i]),
- .R (1'b0),
- .S (1'b0)
- );
-
- FDRSE ff_rd_data_r1
- (
- .Q (rd_data_r1[rd_data_i]),
- .C (clk),
- .CE (1'b1),
- .D (rd_data_r[rd_data_i]),
- .R (1'b0),
- .S (1'b0)
- );
- end
- endgenerate
-
- genvar cmp_data_i;
- generate
- for (cmp_data_i = 0; cmp_data_i < APPDATA_WIDTH;
- cmp_data_i = cmp_data_i + 1) begin: gen_cmp_data
- FDRSE ff_cmp_data
- (
- .Q (cmp_data_r[cmp_data_i]),
- .C (clk),
- .CE (1'b1),
- .D (app_cmp_data[cmp_data_i]),
- .R (1'b0),
- .S (1'b0)
- );
- end
- endgenerate
-
- assign data_fall_r = rd_data_r2[APPDATA_WIDTH-1:(APPDATA_WIDTH/2)];
- assign data_rise_r = rd_data_r2[(APPDATA_WIDTH/2)-1:0];
- assign cmp_data_fall = cmp_data_r[APPDATA_WIDTH-1:(APPDATA_WIDTH/2)];
- assign cmp_data_rise = cmp_data_r[(APPDATA_WIDTH/2)-1:0];
-
- // Instantiate ff for timing.
- FDRSE ff_rd_data_valid_r
- (
- .Q (rd_data_valid_r),
- .C (clk),
- .CE (1'b1),
- .D (rd_data_valid),
- .R (1'b0),
- .S (1'b0)
- );
-
- always @(posedge clk) begin
- if (rst_r1) begin
- rd_data_valid_r1 <= 1'd0;
- end else begin
- rd_data_valid_r1 <= rd_data_valid_r & phy_init_done;
- end
- end
-
- always @(posedge clk)begin
- rd_data_r2 <= rd_data_r1;
- cmp_data_r1 <= cmp_data_r;
- rd_data_valid_r2 <= rd_data_valid_r1;
- end
-
- genvar cmp_i;
- generate
- for (cmp_i = 0; cmp_i < APPDATA_WIDTH/16; cmp_i = cmp_i + 1) begin: gen_cmp
- assign byte_err_fall[cmp_i]
- = (rd_data_valid_r2 &&
- (data_fall_r[8*(cmp_i+1)-1:8*cmp_i] !=
- cmp_data_fall[8*(cmp_i+1)-1:8*cmp_i]));
- assign byte_err_rise[cmp_i]
- = (rd_data_valid_r2 &&
- (data_rise_r[8*(cmp_i+1)-1:8*cmp_i] !=
- cmp_data_rise[8*(cmp_i+1)-1:8*cmp_i]));
- end
- endgenerate
-
- always @(posedge clk) begin
- byte_err_rise_r <= byte_err_rise;
- byte_err_fall_r <= byte_err_fall;
- end
-
- always @(posedge clk)
- if (rst_r1) begin
- err_rise <= 1'bx;
- err_fall <= 1'bx;
- cmp_start <= 1'b0;
- error_tmp_r <= 1'b0;
- end else begin
- err_rise <= | byte_err_rise_r;
- err_fall <= | byte_err_fall_r;
- // start comparing when initialization/calibration complete, and we
- // get first valid readback
- if (rd_data_valid_r2)
- cmp_start <= 1'b1;
- if (cmp_start && !error_tmp_r)
- error_tmp_r <= err_rise | err_fall;
- //synthesis translate_off
- if ((err_rise || err_fall) && cmp_start)
- $display ("ERROR at time %t" , $time);
- //synthesis translate_on
- end
-
- // FF inst to force synthesis to infer ff's.
- // Done for timing.
- FDRSE ff_error_1
- (
- .Q (error_tmp_r1),
- .C (clk),
- .CE (1'b1),
- .D (error_tmp_r),
- .R (1'b0),
- .S (1'b0)
- );
-
- FDRSE ff_error_2
- (
- .Q (error_tmp_r2),
- .C (clk),
- .CE (1'b1),
- .D (error_tmp_r1),
- .R (1'b0),
- .S (1'b0)
- );
-
- always @(posedge clk) begin
- error <= error_tmp_r2;
- error_cmp <= err_rise | err_fall;
- end
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_data_gen.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_data_gen.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_data_gen.v (nonexistent)
@@ -1,294 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_tb_test_data_gen.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Fri Sep 01 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module contains the data generation logic for the synthesizable
-// testbench.
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_tb_test_data_gen #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter DM_WIDTH = 9,
- parameter DQ_WIDTH = 72,
- parameter APPDATA_WIDTH = 144,
- parameter ECC_ENABLE = 0
- )
- (
- input clk,
- input rst,
- input wr_data_en,
- input rd_data_valid,
- input [APPDATA_WIDTH-1:0] bus_if_wr_data,
- input [(APPDATA_WIDTH/8)-1:0] bus_if_wr_mask_data,
- output app_wdf_wren,
- output [APPDATA_WIDTH-1:0] app_wdf_data,
- output [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
- output [APPDATA_WIDTH-1:0] app_cmp_data
- );
-
- localparam RD_IDLE_FIRST_DATA = 2'b00;
- localparam RD_SECOND_DATA = 2'b01;
- localparam RD_THIRD_DATA = 2'b10;
- localparam RD_FOURTH_DATA = 2'b11;
-
- reg [APPDATA_WIDTH-1:0] app_wdf_data_r;
- reg [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data_r;
- wire app_wdf_wren_r;
- reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_fall;
- reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_rise;
- wire rd_data_valid_r;
- reg [1:0] rd_state;
- reg rst_r
- /* synthesis syn_preserve = 1 */;
- reg rst_r1
- /* synthesis syn_maxfan = 10 */;
- wire [APPDATA_WIDTH-1:0] wr_data;
- reg wr_data_en_r;
- reg [(APPDATA_WIDTH/2)-1:0] wr_data_fall
- /* synthesis syn_maxfan = 2 */;
- reg [(APPDATA_WIDTH/2)-1:0] wr_data_rise
- /* synthesis syn_maxfan = 2 */;
- wire [(APPDATA_WIDTH/8)-1:0] wr_mask_data;
- //wire [(APPDATA_WIDTH/16)-1:0] wr_mask_data_fall;
- //wire [(APPDATA_WIDTH/16)-1:0] wr_mask_data_rise;
- //reg [1:0] wr_state;
-
- // XST attributes for local reset "tree"
- // synthesis attribute shreg_extract of rst_r is "no";
- // synthesis attribute shreg_extract of rst_r1 is "no";
- // synthesis attribute equivalent_register_removal of rst_r is "no"
-
- //***************************************************************************
-
- // local reset "tree" for controller logic only. Create this to ease timing
- // on reset path. Prohibit equivalent register removal on RST_R to prevent
- // "sharing" with other local reset trees (caution: make sure global fanout
- // limit is set to larger than fanout on RST_R, otherwise SLICES will be
- // used for fanout control on RST_R.
- always @(posedge clk) begin
- rst_r <= rst;
- rst_r1 <= rst_r;
- end
-
-// always @(posedge clk) begin
-// //app_wdf_data_r <= wr_data;
-// //app_wdf_mask_data_r <= wr_mask_data;
-// app_wdf_data <= wr_data; //app_wdf_data_r;
-// app_wdf_mask_data <= wr_mask_data;//app_wdf_mask_data_r;
-// end
- assign app_wdf_data = wr_data;
- assign app_wdf_mask_data = wr_mask_data;
- // inst ff for timing
- FDRSE ff_wdf_wren
- (
- .Q (app_wdf_wren),
- .C (clk),
- .CE (1'b1),
- .D (wr_data_en), //wr_data_en_r
- .R (1'b0),
- .S (1'b0)
- );
-
-// FDRSE ff_wdf_wren_r
-// (
-// .Q (app_wdf_wren),
-// .C (clk),
-// .CE (1'b1),
-// .D (app_wdf_wren_r),
-// .R (1'b0),
-// .S (1'b0)
-// );
-
- FDRSE ff_rd_data_valid_r
- (
- .Q (rd_data_valid_r),
- .C (clk),
- .CE (1'b1),
- .D (rd_data_valid),
- .R (1'b0),
- .S (1'b0)
- );
-
- assign wr_data = {wr_data_fall, wr_data_rise};
- assign wr_mask_data = bus_if_wr_mask_data;
-
- //data latching
- //synthesis attribute max_fanout of wr_data_fall is 2
- //synthesis attribute max_fanout of wr_data_rise is 2
- always @(posedge clk)
- begin
- if (rst_r1)
- begin
- wr_data_rise <= {(APPDATA_WIDTH/2){1'bx}};
- wr_data_fall <= {(APPDATA_WIDTH/2){1'bx}};
- end
- else
- if (wr_data_en)
- begin
- wr_data_rise <= bus_if_wr_data[(APPDATA_WIDTH/2)-1:0];
- wr_data_fall <= bus_if_wr_data[APPDATA_WIDTH-1:(APPDATA_WIDTH/2)];
- end
- end
-
-// //***************************************************************************
-// // DATA generation for WRITE DATA FIFOs & for READ DATA COMPARE
-// //***************************************************************************
-//
-// assign wr_data = {wr_data_fall, wr_data_rise};
-// assign wr_mask_data = {wr_mask_data_fall, wr_mask_data_rise};
-//
-// //*****************************************************************
-// // For now, don't vary data masks
-// //*****************************************************************
-//
-// assign wr_mask_data_rise = {(APPDATA_WIDTH/8){1'b0}};
-// assign wr_mask_data_fall = {(APPDATA_WIDTH/8){1'b0}};
-//
-// //*****************************************************************
-// // Write data logic
-// //*****************************************************************
-//
-// // write data generation
-// //synthesis attribute max_fanout of wr_data_fall is 2
-// //synthesis attribute max_fanout of wr_data_rise is 2
-// always @(posedge clk) begin
-// if (rst_r1) begin
-// wr_data_rise <= {(APPDATA_WIDTH/2){1'bx}};
-// wr_data_fall <= {(APPDATA_WIDTH/2){1'bx}};
-// wr_state <= WR_IDLE_FIRST_DATA;
-// end else begin
-// case (wr_state)
-// WR_IDLE_FIRST_DATA:
-// if (wr_data_en) begin
-// wr_data_rise <= {(APPDATA_WIDTH/2){1'b1}}; // 0xF
-// wr_data_fall <= {(APPDATA_WIDTH/2){1'b0}}; // 0x0
-// wr_state <= WR_SECOND_DATA;
-// end
-// WR_SECOND_DATA:
-// if (wr_data_en) begin
-// wr_data_rise <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
-// wr_data_fall <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
-// wr_state <= WR_THIRD_DATA;
-// end
-// WR_THIRD_DATA:
-// if (wr_data_en) begin
-// wr_data_rise <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
-// wr_data_fall <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
-// wr_state <= WR_FOURTH_DATA;
-// end
-// WR_FOURTH_DATA:
-// if (wr_data_en) begin
-// wr_data_rise <= {(APPDATA_WIDTH/8){4'b1001}}; // 0x9
-// wr_data_fall <= {(APPDATA_WIDTH/8){4'b0110}}; // 0x6
-// wr_state <= WR_IDLE_FIRST_DATA;
-// end
-// endcase
-// end
-// end
- //another 1 cc delay
-// always @(posedge clk)
-// if (rst_r1)
-// wr_data_en_r <= 1'b0;
-// else
-// wr_data_en_r <= wr_data_en;
-
- //*****************************************************************
- // Read data logic
- //*****************************************************************
-
- // read comparison data generation
- always @(posedge clk)
- if (rst_r1) begin
- rd_data_pat_rise <= {(APPDATA_WIDTH/2){1'bx}};
- rd_data_pat_fall <= {(APPDATA_WIDTH/2){1'bx}};
- rd_state <= RD_IDLE_FIRST_DATA;
- end else begin
- case (rd_state)
- RD_IDLE_FIRST_DATA:
- if (rd_data_valid_r)
- begin
- rd_data_pat_rise <= {(APPDATA_WIDTH/2){1'b1}}; // 0xF
- rd_data_pat_fall <= {(APPDATA_WIDTH/2){1'b0}}; // 0x0
- rd_state <= RD_SECOND_DATA;
- end
- RD_SECOND_DATA:
- if (rd_data_valid_r) begin
- rd_data_pat_rise <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
- rd_data_pat_fall <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
- rd_state <= RD_THIRD_DATA;
- end
- RD_THIRD_DATA:
- if (rd_data_valid_r) begin
- rd_data_pat_rise <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
- rd_data_pat_fall <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
- rd_state <= RD_FOURTH_DATA;
- end
- RD_FOURTH_DATA:
- if (rd_data_valid_r) begin
- rd_data_pat_rise <= {(APPDATA_WIDTH/8){4'b1001}}; // 0x9
- rd_data_pat_fall <= {(APPDATA_WIDTH/8){4'b0110}}; // 0x6
- rd_state <= RD_IDLE_FIRST_DATA;
- end
- endcase
- end
-
- //data to the compare circuit during read
- assign app_cmp_data = {rd_data_pat_fall, rd_data_pat_rise};
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_addr_gen.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_addr_gen.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_test_addr_gen.v (nonexistent)
@@ -1,138 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007, 2008 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_tb_test_addr_gen.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Fri Sep 01 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// The address for the memory and the various user commands can be given
-// through this module. It instantiates the block RAM which stores all the
-// information in particular sequence. The data stored should be in a
-// sequence starting from LSB:
-// column address, row address, bank address, commands.
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_tb_test_addr_gen #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter COL_WIDTH = 10,
- parameter ROW_WIDTH = 14
- )
- (
- input clk,
- input rst,
- input wr_addr_en,
- input rd_op,
- input [30:0] bus_if_addr,
- output [2:0] app_af_cmd,
- output [30:0] app_af_addr,
- output reg app_af_wren
- );
-
- reg wr_addr_en_r1;
- reg [2:0] af_cmd_r;//, af_cmd_r0, af_cmd_r1;
- reg af_wren_r;
- reg rst_r
- /* synthesis syn_preserve = 1 */;
- reg rst_r1
- /* synthesis syn_maxfan = 10 */;
- reg [5:0] wr_addr_r;//wr_addr_cnt;
- reg wr_addr_en_r0;
-
- // XST attributes for local reset "tree"
- // synthesis attribute shreg_extract of rst_r is "no";
- // synthesis attribute shreg_extract of rst_r1 is "no";
- // synthesis attribute equivalent_register_removal of rst_r is "no"
-
- //*****************************************************************
-
- // local reset "tree" for controller logic only. Create this to ease timing
- // on reset path. Prohibit equivalent register removal on RST_R to prevent
- // "sharing" with other local reset trees (caution: make sure global fanout
- // limit is set to larger than fanout on RST_R, otherwise SLICES will be
- // used for fanout control on RST_R.
- always @(posedge clk) begin
- rst_r <= rst;
- rst_r1 <= rst_r;
- end
-
-
- // register backend enables / FIFO enables
- // write enable for Command/Address FIFO is generated 1 CC after WR_ADDR_EN
- always @(posedge clk)
- if (rst_r1) begin
- app_af_wren <= 1'b0;
- end else begin
- app_af_wren <= wr_addr_en;
- end
-
- always @ (posedge clk)
- if (rst_r1)
- wr_addr_r <= 0;
- else if (wr_addr_en && (rd_op == 1'b0))
- wr_addr_r <= bus_if_addr;
-
- assign app_af_addr = wr_addr_r;
- assign app_af_cmd = af_cmd_r;
-
- always @ (posedge clk)
- begin
- af_cmd_r <= 0;
- if (rd_op)
- af_cmd_r <= 3'b001;
- end
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_top.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_top.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_tb_top.v (nonexistent)
@@ -1,255 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_tb_top.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Fri Sep 01 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module is the synthesizable test bench for the memory interface.
-// This Test bench is to compare the write and the read data and generate
-// an error flag.
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_user_if_top #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter COL_WIDTH = 10,
- parameter DM_WIDTH = 9,
- parameter DQ_WIDTH = 72,
- parameter ROW_WIDTH = 14,
- parameter APPDATA_WIDTH = 144,
- parameter ECC_ENABLE = 0,
- parameter BURST_LEN = 4
- )
- (
- input clk0,
- input rst0,
- input app_af_afull,
- input app_wdf_afull,
- input rd_data_valid,
- input [APPDATA_WIDTH-1:0] rd_data_fifo_out,
- input phy_init_done,
- input rd_cmd,
- input wr_cmd,
- input [30:0] bus_if_addr,
- input [APPDATA_WIDTH-1:0] bus_if_wr_data,
- input [(APPDATA_WIDTH/8)-1:0] bus_if_wr_mask_data,
- output end_op,
- output req_wd,
- output app_af_wren,
- output [2:0] app_af_cmd,
- output [30:0] app_af_addr,
- output app_wdf_wren,
- output [APPDATA_WIDTH-1:0] app_wdf_data,
- output [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
- output error,
- output error_cmp
- );
-
- localparam BURST_LEN_DIV2 = BURST_LEN/2;
-
- localparam IDLE_CMD = 3'b000;
- localparam WRITE_CMD = 3'b001;
- localparam READ_CMD = 3'b010;
-
- reg app_af_not_afull_r;
- wire [APPDATA_WIDTH-1:0] app_cmp_data;
- reg app_wdf_not_afull_r ;
- reg [2:0] burst_cnt;
- reg phy_init_done_tb_r;
- wire phy_init_done_r;
- reg rst_r
- /* synthesis syn_preserve = 1 */;
- reg rst_r1
- /* synthesis syn_maxfan = 10 */;
- reg [2:0] state;
- reg [3:0] state_cnt;
- reg wr_addr_en ;
- reg wr_data_en ;
- reg rd_op;
- reg end_op_r;
-
- // XST attributes for local reset "tree"
- // synthesis attribute shreg_extract of rst_r is "no";
- // synthesis attribute shreg_extract of rst_r1 is "no";
- // synthesis attribute equivalent_register_removal of rst_r is "no"
-
- //*****************************************************************
-
- // local reset "tree" for controller logic only. Create this to ease timing
- // on reset path. Prohibit equivalent register removal on RST_R to prevent
- // "sharing" with other local reset trees (caution: make sure global fanout
- // limit is set to larger than fanout on RST_R, otherwise SLICES will be
- // used for fanout control on RST_R.
- always @(posedge clk0) begin
- rst_r <= rst0;
- rst_r1 <= rst_r;
- end
-
- // Instantiate flops for timing.
- FDRSE ff_phy_init_done
- (
- .Q (phy_init_done_r),
- .C (clk0),
- .CE (1'b1),
- .D (phy_init_done),
- .R (1'b0),
- .S (1'b0)
- );
-
- assign end_op = end_op_r;
- //***************************************************************************
- // State Machine for writing to WRITE DATA & ADDRESS FIFOs
- // state machine changed for low FIFO threshold values
- //***************************************************************************
-
- always @(posedge clk0) begin
- if (rst_r1) begin
- wr_data_en <= 1'bx;
- wr_addr_en <= 1'bx;
- state[2:0] <= IDLE_CMD;
- state_cnt <= 4'bxxxx;
- app_af_not_afull_r <= 1'bx;
- app_wdf_not_afull_r <= 1'bx;
- burst_cnt <= 3'bxxx;
- phy_init_done_tb_r <= 1'bx;
- rd_op <= 1'bx;
- end_op_r <= 1'bx;
- end else begin
- wr_data_en <= 1'b0;
- wr_addr_en <= 1'b0;
- rd_op <= 1'b0;
- end_op_r <= 1'b0;
- app_af_not_afull_r <= ~app_af_afull;
- app_wdf_not_afull_r <= ~app_wdf_afull;
- phy_init_done_tb_r <= phy_init_done_r;
-
- case (state)
- IDLE_CMD: begin
- state_cnt <= 4'd0;
- burst_cnt <= BURST_LEN_DIV2 - 1;
- // only start writing when initialization done
- if (app_wdf_not_afull_r && app_af_not_afull_r && phy_init_done_tb_r)
- begin
- if (rd_cmd)
- state <= READ_CMD;
- if (wr_cmd)
- state <= WRITE_CMD;
- end
- end
-
- WRITE_CMD:
- if (app_wdf_not_afull_r && app_af_not_afull_r)
- begin
- wr_data_en <= 1'b1;
- // When we're done with the current burst...
- if (burst_cnt == 3'd0)
- begin
- wr_addr_en <= 1'b1;
- state <= IDLE_CMD;
- end_op_r <= 1'b1;
- end
- else
- burst_cnt <= burst_cnt - 1;
- end
-
- READ_CMD: begin
- burst_cnt <= BURST_LEN_DIV2 - 1;
- if (app_af_not_afull_r)
- begin
- wr_addr_en <= 1'b1;
- rd_op <= 1'b1;
- state <= IDLE_CMD;
- end_op_r <= 1'b1;
- end
- end
- endcase
- end
- end
- assign req_wd = (!wr_addr_en && wr_data_en)? 1'b1:1'b0;
-
- // Command/Address and Write Data generation
- ddr2_tb_test_gen #
- (
- .BANK_WIDTH (BANK_WIDTH),
- .COL_WIDTH (COL_WIDTH),
- .DM_WIDTH (DM_WIDTH),
- .DQ_WIDTH (DQ_WIDTH),
- .APPDATA_WIDTH (APPDATA_WIDTH),
- .ECC_ENABLE (ECC_ENABLE),
- .ROW_WIDTH (ROW_WIDTH)
- )
- u_tb_test_gen
- (
- .clk (clk0),
- .rst (rst0),
- .wr_addr_en (wr_addr_en),
- .wr_data_en (wr_data_en),
- .rd_op (rd_op),
- .rd_data_valid (rd_data_valid),
- .bus_if_addr (bus_if_addr),
- .app_af_wren (app_af_wren),
- .bus_if_wr_mask_data(bus_if_wr_mask_data),
- .bus_if_wr_data (bus_if_wr_data),
- .app_af_cmd (app_af_cmd),
- .app_af_addr (app_af_addr),
- .app_wdf_wren (app_wdf_wren),
- .app_wdf_data (app_wdf_data),
- .app_wdf_mask_data (app_wdf_mask_data)//,
- //.app_cmp_data (app_cmp_data)
- );
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_adr_data_gen.v
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_adr_data_gen.v (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/sim/ddr2_adr_data_gen.v (nonexistent)
@@ -1,273 +0,0 @@
-//*****************************************************************************
-// DISCLAIMER OF LIABILITY
-//
-// This file contains proprietary and confidential information of
-// Xilinx, Inc. ("Xilinx"), that is distributed under a license
-// from Xilinx, and may be used, copied and/or disclosed only
-// pursuant to the terms of a valid license agreement with Xilinx.
-//
-// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-// does not warrant that functions included in the Materials will
-// meet the requirements of Licensee, or that the operation of the
-// Materials will be uninterrupted or error-free, or that defects
-// in the Materials will be corrected. Furthermore, Xilinx does
-// not warrant or make any representations regarding use, or the
-// results of the use, of the Materials in terms of correctness,
-// accuracy, reliability or otherwise.
-//
-// 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.
-//
-// Copyright 2006, 2007 Xilinx, Inc.
-// All rights reserved.
-//
-// This disclaimer and copyright notice must be retained as part
-// of this file at all times.
-//*****************************************************************************
-// ____ ____
-// / /\/ /
-// /___/ \ / Vendor: Xilinx
-// \ \ \/ Version: 3.6.1
-// \ \ Application: MIG
-// / / Filename: ddr2_tb_test_gen.v
-// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
-// \ \ / \ Date Created: Fri Sep 01 2006
-// \___\/\___\
-//
-//Device: Virtex-5
-//Design Name: DDR2
-//Purpose:
-// This module instantiates the addr_gen and the data_gen modules. It takes
-// the user data stored in internal FIFOs and gives the data that is to be
-// compared with the read data
-//Reference:
-//Revision History:
-//*****************************************************************************
-
-`timescale 1ns/1ps
-
-module ddr2_adr_data_gen #
- (
- // Following parameters are for 72-bit RDIMM design (for ML561 Reference
- // board design). Actual values may be different. Actual parameters values
- // are passed from design top module MEMCtrl module. Please refer to
- // the MEMCtrl module for actual values.
- parameter BANK_WIDTH = 2,
- parameter COL_WIDTH = 10,
- parameter DM_WIDTH = 9,
- parameter DQ_WIDTH = 72,
- parameter APPDATA_WIDTH = 144,
- parameter ECC_ENABLE = 0,
- parameter ROW_WIDTH = 14
- )
- (
- input clk,
- input rst,
- input wr_addr_en,
- input wr_data_en,
- input rd_op,
- input rd_data_valid,
- input [30:0] bus_if_addr,
- input [APPDATA_WIDTH-1:0] bus_if_wr_data,
- input [(APPDATA_WIDTH/8)-1:0] bus_if_wr_mask_data,
- output reg app_af_wren,
- output [2:0] app_af_cmd,
- output [30:0] app_af_addr,
- output app_wdf_wren,
- output [APPDATA_WIDTH-1:0] app_wdf_data,
- output [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data//,
- //output [APPDATA_WIDTH-1:0] app_cmp_data
- );
-
- //data
- localparam RD_IDLE_FIRST_DATA = 2'b00;
- localparam RD_SECOND_DATA = 2'b01;
- localparam RD_THIRD_DATA = 2'b10;
- localparam RD_FOURTH_DATA = 2'b11;
-
- //address
- reg wr_addr_en_r1;
- reg [2:0] af_cmd_r;//, af_cmd_r0, af_cmd_r1;
- reg af_wren_r;
- reg rst_r
- /* synthesis syn_preserve = 1 */;
- reg rst_r1
- /* synthesis syn_maxfan = 10 */;
- reg [5:0] wr_addr_r;//wr_addr_cnt;
- reg wr_addr_en_r0;
-
- //data
- reg [APPDATA_WIDTH-1:0] app_wdf_data_r;
- reg [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data_r;
- wire app_wdf_wren_r;
- reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_fall;
- reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_rise;
- //wire rd_data_valid_r;
- reg [1:0] rd_state;
- wire [APPDATA_WIDTH-1:0] wr_data;
- reg wr_data_en_r;
- reg [(APPDATA_WIDTH/2)-1:0] wr_data_fall
- /* synthesis syn_maxfan = 2 */;
- reg [(APPDATA_WIDTH/2)-1:0] wr_data_rise
- /* synthesis syn_maxfan = 2 */;
- wire [(APPDATA_WIDTH/8)-1:0] wr_mask_data;
-
- //***************************************************************************
-
- // local reset "tree" for controller logic only. Create this to ease timing
- // on reset path. Prohibit equivalent register removal on RST_R to prevent
- // "sharing" with other local reset trees (caution: make sure global fanout
- // limit is set to larger than fanout on RST_R, otherwise SLICES will be
- // used for fanout control on RST_R.
- always @(posedge clk) begin
- rst_r <= rst;
- rst_r1 <= rst_r;
- end
-// register backend enables / FIFO enables
- // write enable for Command/Address FIFO is generated 1 CC after WR_ADDR_EN
- always @(posedge clk)
- if (rst_r1) begin
- app_af_wren <= 1'b0;
- end else begin
- app_af_wren <= wr_addr_en;
- end
-
- always @ (posedge clk)
- if (rst_r1)
- wr_addr_r <= 0;
- else if (wr_addr_en && (rd_op == 1'b0))
- wr_addr_r <= bus_if_addr;
-
- assign app_af_addr = wr_addr_r;
- assign app_af_cmd = af_cmd_r;
-
- always @ (posedge clk)
- begin
- af_cmd_r <= 0;
- if (rd_op)
- af_cmd_r <= 3'b001;
- end
-
-// ddr2_tb_test_addr_gen #
-// (
-// .BANK_WIDTH (BANK_WIDTH),
-// .COL_WIDTH (COL_WIDTH),
-// .ROW_WIDTH (ROW_WIDTH)
-// )
-// u_addr_gen
-// (
-// .clk (clk),
-// .rst (rst),
-// .wr_addr_en (wr_addr_en),
-// .rd_op (rd_op),
-// .bus_if_addr (bus_if_addr),
-// .app_af_cmd (app_af_cmd),
-// .app_af_addr (app_af_addr),
-// .app_af_wren (app_af_wren)
-// );
-
- //data
- assign app_wdf_data = wr_data;
- assign app_wdf_mask_data = wr_mask_data;
- // inst ff for timing
- FDRSE ff_wdf_wren
- (
- .Q (app_wdf_wren),
- .C (clk),
- .CE (1'b1),
- .D (wr_data_en), //wr_data_en_r
- .R (1'b0),
- .S (1'b0)
- );
-// FDRSE ff_rd_data_valid_r
-// (
-// .Q (rd_data_valid_r),
-// .C (clk),
-// .CE (1'b1),
-// .D (rd_data_valid),
-// .R (1'b0),
-// .S (1'b0)
-// );
-
- assign wr_data = {wr_data_fall, wr_data_rise};
- assign wr_mask_data = bus_if_wr_mask_data;
-
- //data latching
- //synthesis attribute max_fanout of wr_data_fall is 2
- //synthesis attribute max_fanout of wr_data_rise is 2
- always @(posedge clk)
- begin
- if (rst_r1)
- begin
- wr_data_rise <= {(APPDATA_WIDTH/2){1'bx}};
- wr_data_fall <= {(APPDATA_WIDTH/2){1'bx}};
- end
- else
- if (wr_data_en)
- begin
- wr_data_rise <= bus_if_wr_data[(APPDATA_WIDTH/2)-1:0];
- wr_data_fall <= bus_if_wr_data[APPDATA_WIDTH-1:(APPDATA_WIDTH/2)];
- end
- end
-
- //BO: needs to be commented out in the future
- //*****************************************************************
- // Read data logic
- //*****************************************************************
-//
-// // read comparison data generation
-// always @(posedge clk)
-// if (rst_r1) begin
-// rd_data_pat_rise <= {(APPDATA_WIDTH/2){1'bx}};
-// rd_data_pat_fall <= {(APPDATA_WIDTH/2){1'bx}};
-// rd_state <= RD_IDLE_FIRST_DATA;
-// end else begin
-// case (rd_state)
-// RD_IDLE_FIRST_DATA:
-// if (rd_data_valid_r)
-// begin
-// rd_data_pat_rise <= {(APPDATA_WIDTH/2){1'b1}}; // 0xF
-// rd_data_pat_fall <= {(APPDATA_WIDTH/2){1'b0}}; // 0x0
-// rd_state <= RD_SECOND_DATA;
-// end
-// RD_SECOND_DATA:
-// if (rd_data_valid_r) begin
-// rd_data_pat_rise <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
-// rd_data_pat_fall <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
-// rd_state <= RD_THIRD_DATA;
-// end
-// RD_THIRD_DATA:
-// if (rd_data_valid_r) begin
-// rd_data_pat_rise <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
-// rd_data_pat_fall <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
-// rd_state <= RD_FOURTH_DATA;
-// end
-// RD_FOURTH_DATA:
-// if (rd_data_valid_r) begin
-// rd_data_pat_rise <= {(APPDATA_WIDTH/8){4'b1001}}; // 0x9
-// rd_data_pat_fall <= {(APPDATA_WIDTH/8){4'b0110}}; // 0x6
-// rd_state <= RD_IDLE_FIRST_DATA;
-// end
-// endcase
-// end
-//
-// //data to the compare circuit during read
-// assign app_cmp_data = {rd_data_pat_fall, rd_data_pat_rise};
-
-
-
-
-endmodule
Index: rtl/XilinxMIG_MemCtrl/user_design/sim
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design/sim (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design/sim (nonexistent)
rtl/XilinxMIG_MemCtrl/user_design/sim
Property changes :
Deleted: bugtraq:number
## -1 +0,0 ##
-true
\ No newline at end of property
Index: rtl/XilinxMIG_MemCtrl/user_design
===================================================================
--- rtl/XilinxMIG_MemCtrl/user_design (revision 2)
+++ rtl/XilinxMIG_MemCtrl/user_design (nonexistent)
rtl/XilinxMIG_MemCtrl/user_design
Property changes :
Deleted: bugtraq:number
## -1 +0,0 ##
-true
\ No newline at end of property
Index: rtl/XilinxMIG_MemCtrl
===================================================================
--- rtl/XilinxMIG_MemCtrl (revision 2)
+++ rtl/XilinxMIG_MemCtrl (nonexistent)
rtl/XilinxMIG_MemCtrl
Property changes :
Deleted: bugtraq:number
## -1 +0,0 ##
-true
\ No newline at end of property
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_dqs_iob.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_dqs_iob.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_dqs_iob.v (revision 3)
@@ -0,0 +1,266 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_phy_dqs_iob.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module places the data strobes in the IOBs.
+//Reference:
+//Revision History:
+// Rev 1.1 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
+// Rev 1.2 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
+// on IODELAY primitives. PK. 11/27/08
+// Rev 1.3 - IDDR primitve (u_iddr_dq_ce) is replaced with a negative-edge
+// triggered flip-flop. PK. 03/20/09
+// Rev 1.4 - To fix CR 540201, S and syn_preserve attributes are added
+// for dqs_oe_n_r. PK. 01/08/10
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_dqs_iob #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter DDR_TYPE = 1,
+ parameter HIGH_PERFORMANCE_MODE = "TRUE",
+ parameter IODELAY_GRP = "IODELAY_MIG"
+ )
+ (
+ input clk0,
+ input clkdiv0,
+ input rst0,
+ input dlyinc_dqs,
+ input dlyce_dqs,
+ input dlyrst_dqs,
+ input dlyinc_gate,
+ input dlyce_gate,
+ input dlyrst_gate,
+ input dqs_oe_n,
+ input dqs_rst_n,
+ input en_dqs,
+ inout ddr_dqs,
+ inout ddr_dqs_n,
+ output dq_ce,
+ output delayed_dqs
+ );
+
+ wire clk180;
+ wire dqs_bufio;
+
+ wire dqs_ibuf;
+ wire dqs_idelay;
+ wire dqs_oe_n_delay;
+ (* S = "TRUE" *) wire dqs_oe_n_r /* synthesis syn_preserve = 1*/;
+ wire dqs_rst_n_delay;
+ reg dqs_rst_n_r /* synthesis syn_preserve = 1*/;
+ wire dqs_out;
+ wire en_dqs_sync /* synthesis syn_keep = 1 */;
+
+ // for simulation only. Synthesis should ignore this delay
+ localparam DQS_NET_DELAY = 0.8;
+
+ assign clk180 = ~clk0;
+
+ // add delta delay to inputs clocked by clk180 to avoid delta-delay
+ // simulation issues
+ assign dqs_rst_n_delay = dqs_rst_n;
+ assign dqs_oe_n_delay = dqs_oe_n;
+
+ //***************************************************************************
+ // DQS input-side resources:
+ // - IODELAY (pad -> IDELAY)
+ // - BUFIO (IDELAY -> BUFIO)
+ //***************************************************************************
+
+ // Route DQS from PAD to IDELAY
+ (* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
+ (
+ .DELAY_SRC("I"),
+ .IDELAY_TYPE("VARIABLE"),
+ .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE),
+ .IDELAY_VALUE(0),
+ .ODELAY_VALUE(0)
+ )
+ u_idelay_dqs
+ (
+ .DATAOUT (dqs_idelay),
+ .C (clkdiv0),
+ .CE (dlyce_dqs),
+ .DATAIN (),
+ .IDATAIN (dqs_ibuf),
+ .INC (dlyinc_dqs),
+ .ODATAIN (),
+ .RST (dlyrst_dqs),
+ .T ()
+ );
+
+ // From IDELAY to BUFIO
+ BUFIO u_bufio_dqs
+ (
+ .I (dqs_idelay),
+ .O (dqs_bufio)
+ );
+
+ // To model additional delay of DQS BUFIO + gating network
+ // for behavioral simulation. Make sure to select a delay number smaller
+ // than half clock cycle (otherwise output will not track input changes
+ // because of inertial delay). Duplicate to avoid delta delay issues.
+ assign #(DQS_NET_DELAY) i_delayed_dqs = dqs_bufio;
+ assign #(DQS_NET_DELAY) delayed_dqs = dqs_bufio;
+
+ //***************************************************************************
+ // DQS gate circuit (not supported for all controllers)
+ //***************************************************************************
+
+ // Gate routing:
+ // en_dqs -> IDELAY -> en_dqs_sync -> IDDR.S -> dq_ce ->
+ // capture IDDR.CE
+
+ // Delay CE control so that it's in phase with delayed DQS
+ (* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
+ (
+ .DELAY_SRC ("DATAIN"),
+ .IDELAY_TYPE ("VARIABLE"),
+ .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+ .IDELAY_VALUE (0),
+ .ODELAY_VALUE (0)
+ )
+ u_iodelay_dq_ce
+ (
+ .DATAOUT (en_dqs_sync),
+ .C (clkdiv0),
+ .CE (dlyce_gate),
+ .DATAIN (en_dqs),
+ .IDATAIN (),
+ .INC (dlyinc_gate),
+ .ODATAIN (),
+ .RST (dlyrst_gate),
+ .T ()
+ );
+
+ // Generate sync'ed CE to DQ IDDR's using a negative-edge triggered flip-flop
+ // clocked by DQS. This flop should be locked to the IOB flip-flop at the same
+ // site as IODELAY u_idelay_dqs in order to use the dedicated route from
+ // the IODELAY to flip-flop (to keep this route as short as possible)
+ (* IOB = "FORCE" *) FDCPE_1 #
+ (
+ .INIT(1'b0)
+ )
+ u_iddr_dq_ce
+ (
+ .Q (dq_ce),
+ .C (i_delayed_dqs),
+ .CE (1'b1),
+ .CLR (1'b0),
+ .D (en_dqs_sync),
+ .PRE (en_dqs_sync)
+ ) /* synthesis syn_useioff = 1 */
+ /* synthesis syn_replicate = 0 */;
+
+ //***************************************************************************
+ // DQS output-side resources
+ //***************************************************************************
+
+ // synthesis attribute keep of dqs_rst_n_r is "true"
+ always @(posedge clk180)
+ dqs_rst_n_r <= dqs_rst_n_delay;
+
+ ODDR #
+ (
+ .SRTYPE("SYNC"),
+ .DDR_CLK_EDGE("OPPOSITE_EDGE")
+ )
+ u_oddr_dqs
+ (
+ .Q (dqs_out),
+ .C (clk180),
+ .CE (1'b1),
+ .D1 (dqs_rst_n_r), // keep output deasserted for write preamble
+ .D2 (1'b0),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ (* IOB = "FORCE" *) FDP u_tri_state_dqs
+ (
+ .D (dqs_oe_n_delay),
+ .Q (dqs_oe_n_r),
+ .C (clk180),
+ .PRE (rst0)
+ ) /* synthesis syn_useioff = 1 */;
+
+ //***************************************************************************
+
+ // use either single-ended (for DDR1) or differential (for DDR2) DQS input
+
+ generate
+ if (DDR_TYPE > 0) begin: gen_dqs_iob_ddr2
+ IOBUFDS u_iobuf_dqs
+ (
+ .O (dqs_ibuf),
+ .IO (ddr_dqs),
+ .IOB (ddr_dqs_n),
+ .I (dqs_out),
+ .T (dqs_oe_n_r)
+ );
+ end else begin: gen_dqs_iob_ddr1
+ IOBUF u_iobuf_dqs
+ (
+ .O (dqs_ibuf),
+ .IO (ddr_dqs),
+ .I (dqs_out),
+ .T (dqs_oe_n_r)
+ );
+ end
+ endgenerate
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_top.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_top.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_top.v (revision 3)
@@ -0,0 +1,276 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_top.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// System level module. This level contains just the memory controller.
+// This level will be intiantated when the user wants to remove the
+// synthesizable test bench, IDELAY control block and the clock
+// generation modules.
+//Reference:
+//Revision History:
+// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
+// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
+// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_top #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2, // # of memory bank addr bits
+ parameter CKE_WIDTH = 1, // # of memory clock enable outputs
+ parameter CLK_WIDTH = 1, // # of clock outputs
+ parameter COL_WIDTH = 10, // # of memory column bits
+ parameter CS_NUM = 1, // # of separate memory chip selects
+ parameter CS_BITS = 0, // set to log2(CS_NUM) (rounded up)
+ parameter CS_WIDTH = 1, // # of total memory chip selects
+ parameter USE_DM_PORT = 1, // enable Data Mask (=1 enable)
+ parameter DM_WIDTH = 9, // # of data mask bits
+ parameter DQ_WIDTH = 72, // # of data width
+ parameter DQ_BITS = 7, // set to log2(DQS_WIDTH*DQ_PER_DQS)
+ parameter DQ_PER_DQS = 8, // # of DQ data bits per strobe
+ parameter DQS_WIDTH = 9, // # of DQS strobes
+ parameter DQS_BITS = 4, // set to log2(DQS_WIDTH)
+ parameter HIGH_PERFORMANCE_MODE = "TRUE", // IODELAY Performance Mode
+ parameter IODELAY_GRP = "IODELAY_MIG", // IODELAY Group Name
+ parameter ODT_WIDTH = 1, // # of memory on-die term enables
+ parameter ROW_WIDTH = 14, // # of memory row & # of addr bits
+ parameter APPDATA_WIDTH = 144, // # of usr read/write data bus bits
+ parameter ADDITIVE_LAT = 0, // additive write latency
+ parameter BURST_LEN = 4, // burst length (in double words)
+ parameter BURST_TYPE = 0, // burst type (=0 seq; =1 interlved)
+ parameter CAS_LAT = 5, // CAS latency
+ parameter ECC_ENABLE = 0, // enable ECC (=1 enable)
+ parameter ODT_TYPE = 1, // ODT (=0(none),=1(75),=2(150),=3(50))
+ parameter MULTI_BANK_EN = 1, // enable bank management
+ parameter TWO_T_TIME_EN = 0, // 2t timing for unbuffered dimms
+ parameter REDUCE_DRV = 0, // reduced strength mem I/O (=1 yes)
+ parameter REG_ENABLE = 1, // registered addr/ctrl (=1 yes)
+ parameter TREFI_NS = 7800, // auto refresh interval (ns)
+ parameter TRAS = 40000, // active->precharge delay
+ parameter TRCD = 15000, // active->read/write delay
+ parameter TRFC = 105000, // ref->ref, ref->active delay
+ parameter TRP = 15000, // precharge->command delay
+ parameter TRTP = 7500, // read->precharge delay
+ parameter TWR = 15000, // used to determine wr->prech
+ parameter TWTR = 10000, // write->read delay
+ parameter CLK_PERIOD = 3000, // Core/Mem clk period (in ps)
+ parameter SIM_ONLY = 0, // = 1 to skip power up delay
+ parameter DEBUG_EN = 0, // Enable debug signals/controls
+ parameter FPGA_SPEED_GRADE = 2 // FPGA Speed Grade
+ )
+ (
+ input clk0,
+ input clk90,
+ input clkdiv0,
+ input rst0,
+ input rst90,
+ input rstdiv0,
+ input [2:0] app_af_cmd,
+ input [30:0] app_af_addr,
+ input app_af_wren,
+ input app_wdf_wren,
+ input [APPDATA_WIDTH-1:0] app_wdf_data,
+ input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
+ output app_af_afull,
+ output app_wdf_afull,
+ output rd_data_valid,
+ output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
+ output [1:0] rd_ecc_error,
+ output phy_init_done,
+ output [CLK_WIDTH-1:0] ddr2_ck,
+ output [CLK_WIDTH-1:0] ddr2_ck_n,
+ output [ROW_WIDTH-1:0] ddr2_a,
+ output [BANK_WIDTH-1:0] ddr2_ba,
+ output ddr2_ras_n,
+ output ddr2_cas_n,
+ output ddr2_we_n,
+ output [CS_WIDTH-1:0] ddr2_cs_n,
+ output [CKE_WIDTH-1:0] ddr2_cke,
+ output [ODT_WIDTH-1:0] ddr2_odt,
+ output [DM_WIDTH-1:0] ddr2_dm,
+ inout [DQS_WIDTH-1:0] ddr2_dqs,
+ inout [DQS_WIDTH-1:0] ddr2_dqs_n,
+ inout [DQ_WIDTH-1:0] ddr2_dq,
+ // Debug signals (optional use)
+ input dbg_idel_up_all,
+ input dbg_idel_down_all,
+ input dbg_idel_up_dq,
+ input dbg_idel_down_dq,
+ input dbg_idel_up_dqs,
+ input dbg_idel_down_dqs,
+ input dbg_idel_up_gate,
+ input dbg_idel_down_gate,
+ input [DQ_BITS-1:0] dbg_sel_idel_dq,
+ input dbg_sel_all_idel_dq,
+ input [DQS_BITS:0] dbg_sel_idel_dqs,
+ input dbg_sel_all_idel_dqs,
+ input [DQS_BITS:0] dbg_sel_idel_gate,
+ input dbg_sel_all_idel_gate,
+ output [3:0] dbg_calib_done,
+ output [3:0] dbg_calib_err,
+ output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
+ output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
+ );
+
+ // memory initialization/control logic
+ ddr2_mem_if_top #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .CKE_WIDTH (CKE_WIDTH),
+ .CLK_WIDTH (CLK_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .CS_BITS (CS_BITS),
+ .CS_NUM (CS_NUM),
+ .CS_WIDTH (CS_WIDTH),
+ .USE_DM_PORT (USE_DM_PORT),
+ .DM_WIDTH (DM_WIDTH),
+ .DQ_WIDTH (DQ_WIDTH),
+ .DQ_BITS (DQ_BITS),
+ .DQ_PER_DQS (DQ_PER_DQS),
+ .DQS_BITS (DQS_BITS),
+ .DQS_WIDTH (DQS_WIDTH),
+ .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+ .IODELAY_GRP (IODELAY_GRP),
+ .ODT_WIDTH (ODT_WIDTH),
+ .ROW_WIDTH (ROW_WIDTH),
+ .APPDATA_WIDTH (APPDATA_WIDTH),
+ .ADDITIVE_LAT (ADDITIVE_LAT),
+ .BURST_LEN (BURST_LEN),
+ .BURST_TYPE (BURST_TYPE),
+ .CAS_LAT (CAS_LAT),
+ .ECC_ENABLE (ECC_ENABLE),
+ .MULTI_BANK_EN (MULTI_BANK_EN),
+ .TWO_T_TIME_EN (TWO_T_TIME_EN),
+ .ODT_TYPE (ODT_TYPE),
+ .DDR_TYPE (1),
+ .REDUCE_DRV (REDUCE_DRV),
+ .REG_ENABLE (REG_ENABLE),
+ .TREFI_NS (TREFI_NS),
+ .TRAS (TRAS),
+ .TRCD (TRCD),
+ .TRFC (TRFC),
+ .TRP (TRP),
+ .TRTP (TRTP),
+ .TWR (TWR),
+ .TWTR (TWTR),
+ .CLK_PERIOD (CLK_PERIOD),
+ .SIM_ONLY (SIM_ONLY),
+ .DEBUG_EN (DEBUG_EN),
+ .FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
+ )
+ u_mem_if_top
+ (
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .clkdiv0 (clkdiv0),
+ .rst0 (rst0),
+ .rst90 (rst90),
+ .rstdiv0 (rstdiv0),
+ .app_af_cmd (app_af_cmd),
+ .app_af_addr (app_af_addr),
+ .app_af_wren (app_af_wren),
+ .app_wdf_wren (app_wdf_wren),
+ .app_wdf_data (app_wdf_data),
+ .app_wdf_mask_data (app_wdf_mask_data),
+ .app_af_afull (app_af_afull),
+ .app_wdf_afull (app_wdf_afull),
+ .rd_data_valid (rd_data_valid),
+ .rd_data_fifo_out (rd_data_fifo_out),
+ .rd_ecc_error (rd_ecc_error),
+ .phy_init_done (phy_init_done),
+ .ddr_ck (ddr2_ck),
+ .ddr_ck_n (ddr2_ck_n),
+ .ddr_addr (ddr2_a),
+ .ddr_ba (ddr2_ba),
+ .ddr_ras_n (ddr2_ras_n),
+ .ddr_cas_n (ddr2_cas_n),
+ .ddr_we_n (ddr2_we_n),
+ .ddr_cs_n (ddr2_cs_n),
+ .ddr_cke (ddr2_cke),
+ .ddr_odt (ddr2_odt),
+ .ddr_dm (ddr2_dm),
+ .ddr_dqs (ddr2_dqs),
+ .ddr_dqs_n (ddr2_dqs_n),
+ .ddr_dq (ddr2_dq),
+ .dbg_idel_up_all (dbg_idel_up_all),
+ .dbg_idel_down_all (dbg_idel_down_all),
+ .dbg_idel_up_dq (dbg_idel_up_dq),
+ .dbg_idel_down_dq (dbg_idel_down_dq),
+ .dbg_idel_up_dqs (dbg_idel_up_dqs),
+ .dbg_idel_down_dqs (dbg_idel_down_dqs),
+ .dbg_idel_up_gate (dbg_idel_up_gate),
+ .dbg_idel_down_gate (dbg_idel_down_gate),
+ .dbg_sel_idel_dq (dbg_sel_idel_dq),
+ .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
+ .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
+ .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
+ .dbg_sel_idel_gate (dbg_sel_idel_gate),
+ .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
+ .dbg_calib_done (dbg_calib_done),
+ .dbg_calib_err (dbg_calib_err),
+ .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
+ .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
+ .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
+ .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
+ .dbg_calib_rden_dly (dbg_calib_rden_dly),
+ .dbg_calib_gate_dly (dbg_calib_gate_dly)
+ );
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_ctrl.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_ctrl.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_ctrl.v (revision 3)
@@ -0,0 +1,1230 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_ctrl.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 30 2006
+// \___\/\___\
+//
+//
+//Device: Virtex-5
+//Design Name: DDR/DDR2
+//Purpose:
+// This module is the main control logic of the memory interface. All
+// commands are issued from here according to the burst, CAS Latency and the
+// user commands.
+//Reference:
+//Revision History:
+// Rev 1.2 - Fixed auto refresh to activate bug. KP 11-19-2007
+// Rev 1.3 - For Dual Rank parts support CS logic modified. KP. 05/08/08
+// Rev 1.4 - AUTO_REFRESH_WAIT state modified for Auto Refresh flag asserted
+// immediately after calibration is completed. KP. 07/28/08
+// Rev 1.5 - Assignment of bank_valid_r is modified to fix a bug in
+// Bank Management logic. PK. 10/29/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_ctrl #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter COL_WIDTH = 10,
+ parameter CS_BITS = 0,
+ parameter CS_NUM = 1,
+ parameter ROW_WIDTH = 14,
+ parameter ADDITIVE_LAT = 0,
+ parameter BURST_LEN = 4,
+ parameter CAS_LAT = 5,
+ parameter ECC_ENABLE = 0,
+ parameter REG_ENABLE = 1,
+ parameter TREFI_NS = 7800,
+ parameter TRAS = 40000,
+ parameter TRCD = 15000,
+ parameter TRRD = 10000,
+ parameter TRFC = 105000,
+ parameter TRP = 15000,
+ parameter TRTP = 7500,
+ parameter TWR = 15000,
+ parameter TWTR = 10000,
+ parameter CLK_PERIOD = 3000,
+ parameter MULTI_BANK_EN = 1,
+ parameter TWO_T_TIME_EN = 0,
+ parameter DDR_TYPE = 1
+ )
+ (
+ input clk,
+ input rst,
+ input [2:0] af_cmd,
+ input [30:0] af_addr,
+ input af_empty,
+ input phy_init_done,
+ output ctrl_ref_flag,
+ output ctrl_af_rden,
+ output reg ctrl_wren,
+ output reg ctrl_rden,
+ output [ROW_WIDTH-1:0] ctrl_addr,
+ output [BANK_WIDTH-1:0] ctrl_ba,
+ output ctrl_ras_n,
+ output ctrl_cas_n,
+ output ctrl_we_n,
+ output [CS_NUM-1:0] ctrl_cs_n
+ );
+
+ // input address split into various ranges
+ localparam ROW_RANGE_START = COL_WIDTH;
+ localparam ROW_RANGE_END = ROW_WIDTH + ROW_RANGE_START - 1;
+ localparam BANK_RANGE_START = ROW_RANGE_END + 1;
+ localparam BANK_RANGE_END = BANK_WIDTH + BANK_RANGE_START - 1;
+ localparam CS_RANGE_START = BANK_RANGE_START + BANK_WIDTH;
+ localparam CS_RANGE_END = CS_BITS + CS_RANGE_START - 1;
+ // compare address (for determining bank/row hits) split into various ranges
+ // (compare address doesn't include column bits)
+ localparam CMP_WIDTH = CS_BITS + BANK_WIDTH + ROW_WIDTH;
+ localparam CMP_ROW_RANGE_START = 0;
+ localparam CMP_ROW_RANGE_END = ROW_WIDTH + CMP_ROW_RANGE_START - 1;
+ localparam CMP_BANK_RANGE_START = CMP_ROW_RANGE_END + 1;
+ localparam CMP_BANK_RANGE_END = BANK_WIDTH + CMP_BANK_RANGE_START - 1;
+ localparam CMP_CS_RANGE_START = CMP_BANK_RANGE_END + 1;
+ localparam CMP_CS_RANGE_END = CS_BITS + CMP_CS_RANGE_START-1;
+
+ localparam BURST_LEN_DIV2 = BURST_LEN / 2;
+ localparam OPEN_BANK_NUM = 4;
+ localparam CS_BITS_FIX = (CS_BITS == 0) ? 1 : CS_BITS;
+
+ // calculation counters based on clock cycle and memory parameters
+ // TRAS: ACTIVE->PRECHARGE interval - 2
+ localparam integer TRAS_CYC = (TRAS + CLK_PERIOD)/CLK_PERIOD;
+ // TRCD: ACTIVE->READ/WRITE interval - 3 (for DDR2 factor in ADD_LAT)
+ localparam integer TRRD_CYC = (TRRD + CLK_PERIOD)/CLK_PERIOD;
+ localparam integer TRCD_CYC = (((TRCD + CLK_PERIOD)/CLK_PERIOD) >
+ ADDITIVE_LAT )?
+ ((TRCD+CLK_PERIOD)/ CLK_PERIOD) - ADDITIVE_LAT : 0;
+ // TRFC: REFRESH->REFRESH, REFRESH->ACTIVE interval - 2
+ localparam integer TRFC_CYC = (TRFC + CLK_PERIOD)/CLK_PERIOD;
+ // TRP: PRECHARGE->COMMAND interval - 2
+ // for precharge all add 1 extra clock cycle
+ localparam integer TRP_CYC = ((TRP + CLK_PERIOD)/CLK_PERIOD) +1;
+ // TRTP: READ->PRECHARGE interval - 2 (Al + BL/2 + (max (TRTP, 2tck))-2
+ localparam integer TRTP_TMP_MIN = (((TRTP + CLK_PERIOD)/CLK_PERIOD) >= 2)?
+ ((TRTP + CLK_PERIOD)/CLK_PERIOD) : 2;
+ localparam integer TRTP_CYC = TRTP_TMP_MIN + ADDITIVE_LAT
+ + BURST_LEN_DIV2 - 2;
+ // TWR: WRITE->PRECHARGE interval - 2
+ localparam integer WR_LAT = (DDR_TYPE > 0) ? CAS_LAT + ADDITIVE_LAT - 1 : 1;
+ localparam integer TWR_CYC = ((TWR + CLK_PERIOD)/CLK_PERIOD) +
+ WR_LAT + BURST_LEN_DIV2 ;
+ // TWTR: WRITE->READ interval - 3 (for DDR1, TWTR = 2 clks)
+ // DDR2 = CL-1 + BL/2 +TWTR
+ localparam integer TWTR_TMP_MIN = ((TWTR + CLK_PERIOD) % CLK_PERIOD)?((TWTR + CLK_PERIOD)/CLK_PERIOD) + 1:(TWTR + CLK_PERIOD)/CLK_PERIOD;
+ localparam integer TWTR_CYC = (DDR_TYPE > 0) ? (TWTR_TMP_MIN + (CAS_LAT -1)
+ + BURST_LEN_DIV2 ): 2;
+
+ // TRTW: READ->WRITE interval - 3
+ // DDR1: CL + (BL/2)
+ // DDR2: (BL/2) + 2. Two more clocks are added to
+ // the DDR2 counter to account for the delay in
+ // arrival of the DQS during reads (pcb trace + buffer
+ // delays + memory parameters).
+ localparam TRTW_CYC = (DDR_TYPE > 0) ? BURST_LEN_DIV2 + 4 :
+ (CAS_LAT == 25) ? 2 + BURST_LEN_DIV2 : CAS_LAT + BURST_LEN_DIV2;
+
+ localparam integer CAS_LAT_RD = (CAS_LAT == 25) ? 2 : CAS_LAT;
+
+ // Make sure all values >= 0 (some may be = 0)
+ localparam TRAS_COUNT = (TRAS_CYC > 0) ? TRAS_CYC : 0;
+ localparam TRCD_COUNT = (TRCD_CYC > 0) ? TRCD_CYC : 0;
+ localparam TRRD_COUNT = (TRRD_CYC > 0) ? TRRD_CYC : 0;
+ localparam TRFC_COUNT = (TRFC_CYC > 0) ? TRFC_CYC : 0;
+ localparam TRP_COUNT = (TRP_CYC > 0) ? TRP_CYC : 0;
+ localparam TRTP_COUNT = (TRTP_CYC > 0) ? TRTP_CYC : 0;
+ localparam TWR_COUNT = (TWR_CYC > 0) ? TWR_CYC : 0;
+ localparam TWTR_COUNT = (TWTR_CYC > 0) ? TWTR_CYC : 0;
+ localparam TRTW_COUNT = (TRTW_CYC > 0) ? TRTW_CYC : 0;
+
+ // Auto refresh interval
+ localparam TREFI_COUNT = ((TREFI_NS * 1000)/CLK_PERIOD) - 1;
+
+ // memory controller states
+ localparam CTRL_IDLE = 5'h00;
+ localparam CTRL_PRECHARGE = 5'h01;
+ localparam CTRL_PRECHARGE_WAIT = 5'h02;
+ localparam CTRL_AUTO_REFRESH = 5'h03;
+ localparam CTRL_AUTO_REFRESH_WAIT = 5'h04;
+ localparam CTRL_ACTIVE = 5'h05;
+ localparam CTRL_ACTIVE_WAIT = 5'h06;
+ localparam CTRL_BURST_READ = 5'h07;
+ localparam CTRL_READ_WAIT = 5'h08;
+ localparam CTRL_BURST_WRITE = 5'h09;
+ localparam CTRL_WRITE_WAIT = 5'h0A;
+ localparam CTRL_PRECHARGE_WAIT1 = 5'h0B;
+
+
+ reg [CMP_WIDTH-1:0] act_addr_r;
+ wire [30:0] af_addr_r;
+ reg [30:0] af_addr_r1;
+ reg [30:0] af_addr_r2;
+ reg [30:0] af_addr_r3;
+ wire [2:0] af_cmd_r;
+ reg [2:0] af_cmd_r1;
+ reg [2:0] af_cmd_r2;
+ reg af_valid_r;
+ reg af_valid_r1;
+ reg af_valid_r2;
+ reg [CS_BITS_FIX :0] auto_cnt_r;
+ reg auto_ref_r;
+ reg [(OPEN_BANK_NUM*CMP_WIDTH)-1:0] bank_cmp_addr_r;
+ reg [OPEN_BANK_NUM-1:0] bank_hit;
+ reg [OPEN_BANK_NUM-1:0] bank_hit_r;
+ reg [OPEN_BANK_NUM-1:0] bank_hit_r1;
+ reg [OPEN_BANK_NUM-1:0] bank_valid_r;
+ reg bank_conflict_r;
+ reg conflict_resolved_r;
+ reg ctrl_af_rden_r;
+ reg conflict_detect_r;
+ wire conflict_detect;
+ reg cs_change_r;
+ reg cs_change_sticky_r;
+ reg [ROW_WIDTH-1:0] ddr_addr_r;
+ wire [ROW_WIDTH-1:0] ddr_addr_col;
+ wire [ROW_WIDTH-1:0] ddr_addr_row;
+ reg [BANK_WIDTH-1:0] ddr_ba_r;
+ reg ddr_cas_n_r;
+ reg [CS_NUM-1:0] ddr_cs_n_r;
+ reg ddr_ras_n_r;
+ reg ddr_we_n_r;
+ reg [4:0] next_state;
+ reg no_precharge_wait_r;
+ reg no_precharge_r;
+ reg no_precharge_r1;
+ reg phy_init_done_r;
+ reg [4:0] precharge_ok_cnt_r;
+ reg precharge_ok_r;
+ reg [4:0] ras_cnt_r;
+ reg [3:0] rcd_cnt_r;
+ reg rcd_cnt_ok_r;
+ reg [2:0] rdburst_cnt_r;
+ reg rdburst_ok_r;
+ reg rdburst_rden_ok_r;
+ reg rd_af_flag_r;
+ wire rd_flag;
+ reg rd_flag_r;
+ reg [4:0] rd_to_wr_cnt_r;
+ reg rd_to_wr_ok_r;
+ reg ref_flag_r;
+ reg [11:0] refi_cnt_r;
+ reg refi_cnt_ok_r;
+ reg rst_r
+ /* synthesis syn_preserve = 1 */;
+ reg rst_r1
+ /* synthesis syn_maxfan = 10 */;
+ reg [7:0] rfc_cnt_r;
+ reg rfc_ok_r;
+ reg [3:0] row_miss;
+ reg [3:0] row_conflict_r;
+ reg [3:0] rp_cnt_r;
+ reg rp_cnt_ok_r;
+ reg [CMP_WIDTH-1:0] sb_open_add_r;
+ reg [4:0] state_r;
+ reg [4:0] state_r1;
+ wire sm_rden;
+ reg sm_rden_r;
+ reg [2:0] trrd_cnt_r;
+ reg trrd_cnt_ok_r;
+ reg [2:0] two_t_enable_r;
+ reg [CS_NUM-1:0] two_t_enable_r1;
+ reg [2:0] wrburst_cnt_r;
+ reg wrburst_ok_r;
+ reg wrburst_wren_ok_r;
+ wire wr_flag;
+ reg wr_flag_r;
+ reg [4:0] wr_to_rd_cnt_r;
+ reg wr_to_rd_ok_r;
+
+ // XST attributes for local reset "tree"
+ // synthesis attribute shreg_extract of rst_r is "no";
+ // synthesis attribute shreg_extract of rst_r1 is "no";
+ // synthesis attribute equivalent_register_removal of rst_r is "no"
+
+ //***************************************************************************
+
+ // sm_rden is used to assert read enable to the address FIFO
+ assign sm_rden = ((state_r == CTRL_BURST_WRITE) ||
+ (state_r == CTRL_BURST_READ)) ;
+
+ // assert read flag to the adress FIFO
+ assign ctrl_af_rden = sm_rden || rd_af_flag_r;
+
+ // local reset "tree" for controller logic only. Create this to ease timing
+ // on reset path. Prohibit equivalent register removal on RST_R to prevent
+ // "sharing" with other local reset trees (caution: make sure global fanout
+ // limit is set to large enough value, otherwise SLICES may be used for
+ // fanout control on RST_R.
+ always @(posedge clk) begin
+ rst_r <= rst;
+ rst_r1 <= rst_r;
+ end
+
+ //*****************************************************************
+ // interpret commands from Command/Address FIFO
+ //*****************************************************************
+
+ assign wr_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b000) ? 1'b1 : 1'b0): 1'b0;
+ assign rd_flag = (af_valid_r2) ? ((af_cmd_r2 == 3'b001) ? 1'b1 : 1'b0): 1'b0;
+
+ always @(posedge clk) begin
+ rd_flag_r <= rd_flag;
+ wr_flag_r <= wr_flag;
+ end
+
+ //////////////////////////////////////////////////
+ // The data from the address FIFO is fetched and
+ // stored in two register stages. The data will be
+ // pulled out of the second register stage whenever
+ // the state machine can handle new data from the
+ // address FIFO.
+
+ // This flag is asserted when there is no
+ // cmd & address in the pipe. When there is
+ // valid cmd & addr from the address FIFO the
+ // af_valid signals will be asserted. This flag will
+ // be set the cycle af_valid_r is de-asserted.
+ always @(posedge clk) begin
+ // for simulation purposes - to force CTRL_AF_RDEN low during reset
+ if (rst_r1)
+ rd_af_flag_r <= 1'd0;
+ else if((ctrl_af_rden_r) ||
+ (rd_af_flag_r && (af_valid_r || af_valid_r1)))
+ rd_af_flag_r <= 1'd0;
+ else if (~af_valid_r1 || ~af_valid_r)
+ rd_af_flag_r <= 1'd1;
+
+ end
+
+ // First register stage for the cmd & add from the FIFO.
+ // The af_valid_r signal gives the status of the data
+ // in this stage. The af_valid_r will be asserted when there
+ // is valid data. This register stage will be updated
+ // 1. read to the FIFO and the FIFO not empty
+ // 2. After write and read states
+ // 3. The valid signal is not asserted in the last stage.
+ always @(posedge clk) begin
+ if (rst_r1)begin
+ af_valid_r <= 1'd0;
+ end else begin
+ if (ctrl_af_rden_r || sm_rden_r || ~af_valid_r1
+ || ~af_valid_r2)begin
+ af_valid_r <= ctrl_af_rden_r;
+ end
+ end
+ end
+
+ // The output register in the FIFO is used. The addr
+ // and command are already registered in the FIFO.
+ assign af_addr_r = af_addr;
+ assign af_cmd_r = af_cmd;
+
+ // Second register stage for the cmd & add from the FIFO.
+ // The af_valid_r1 signal gives the status of the data
+ // in this stage. The af_valid_r will be asserted when there
+ // is valid data. This register stage will be updated
+ // 1. read to the FIFO and the FIFO not empty and there
+ // is no valid data on this stage
+ // 2. After write and read states
+ // 3. The valid signal is not asserted in the last stage.
+ always@(posedge clk) begin
+ if (rst_r1)begin
+ af_valid_r1 <= 1'd0;
+ af_addr_r1 <= {31{1'bx}};
+ af_cmd_r1 <= {3{1'bx}};
+ end else if (~af_valid_r1 || sm_rden_r ||
+ ~af_valid_r2) begin
+ af_valid_r1 <= af_valid_r;
+ af_addr_r1 <= af_addr_r;
+ af_cmd_r1 <= af_cmd_r;
+ end
+ end
+
+ // The state machine uses the address and command in this
+ // register stage. The data is fetched from the second
+ // register stage whenever the state machine can accept new
+ // addr. The conflict flags are also generated based on the
+ // second register stage and updated when the new address
+ // is loaded for the state machine.
+ always@(posedge clk) begin
+ if (rst_r1)begin
+ af_valid_r2 <= 1'd0;
+ af_addr_r2 <= {31{1'bx}};
+ af_cmd_r2 <= {3{1'bx}};
+ bank_hit_r <= {OPEN_BANK_NUM{1'bx}};
+ bank_conflict_r <= 1'bx;
+ row_conflict_r <= 4'bx;
+ end else if(sm_rden || ~af_valid_r2)begin
+ af_valid_r2 <= af_valid_r1;
+ af_addr_r2 <= af_addr_r1;
+ af_cmd_r2 <= af_cmd_r1;
+ if(MULTI_BANK_EN)begin
+ bank_hit_r <= bank_hit;
+ row_conflict_r <= row_miss;
+ bank_conflict_r <= (~(|bank_hit));
+ end else begin
+ bank_hit_r <= {OPEN_BANK_NUM{1'b0}};
+ bank_conflict_r <= 1'd0;
+ row_conflict_r[0] <= (af_addr_r1[CS_RANGE_END:ROW_RANGE_START]
+ != sb_open_add_r[CMP_WIDTH-1:0]);
+ end
+ end
+ end // always@ (posedge clk)
+
+ //detecting cs change for multi chip select case
+ generate
+ if(CS_NUM > 1) begin: gen_cs_change
+ always @(posedge clk) begin
+ if(sm_rden || ~af_valid_r2)begin
+ cs_change_r <= af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
+ af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
+ cs_change_sticky_r <=
+ af_addr_r1[CS_RANGE_END:CS_RANGE_START] !=
+ af_addr_r2[CS_RANGE_END:CS_RANGE_START] ;
+ end else
+ cs_change_r <= 1'd0;
+ end
+ end // block: gen_cs_change
+ else begin: gen_cs_0
+ always @(posedge clk) begin
+ cs_change_r <= 1'd0;
+ cs_change_sticky_r <= 1'd0;
+ end
+ end
+ endgenerate
+
+ assign conflict_detect = (MULTI_BANK_EN) ?
+ ((|(row_conflict_r[3:0] & bank_hit_r[3:0]))
+ | bank_conflict_r) & af_valid_r2 :
+ row_conflict_r[0] & af_valid_r2;
+
+ always @(posedge clk) begin
+ conflict_detect_r <= conflict_detect;
+ sm_rden_r <= sm_rden;
+ af_addr_r3 <= af_addr_r2;
+ ctrl_af_rden_r <= ctrl_af_rden & ~af_empty;
+ end
+
+ // conflict resolved signal. When this signal is asserted
+ // the conflict is resolved. The address to be compared
+ // for the conflict_resolved_r will be stored in act_add_r
+ // when the bank is opened.
+ always @(posedge clk) begin
+ conflict_resolved_r <= (act_addr_r ==
+ af_addr_r2[CS_RANGE_END:ROW_RANGE_START]);
+ if((state_r == CTRL_ACTIVE))
+ act_addr_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
+ end
+
+ //***************************************************************************
+ // Bank management logic
+ // Semi-hardcoded for now for 4 banks
+ // will keep multiple banks open if MULTI_BANK_EN is true.
+ //***************************************************************************
+
+ genvar bank_i;
+ generate // if multiple bank option chosen
+ if(MULTI_BANK_EN) begin: gen_multi_bank_open
+
+ for (bank_i = 0; bank_i < OPEN_BANK_NUM;
+ bank_i = bank_i + 1) begin: gen_bank_hit1
+ // asserted if bank address match + open bank entry is valid
+ always @(*) begin
+ bank_hit[bank_i]
+ = ((bank_cmp_addr_r[(CMP_WIDTH*(bank_i+1))-1:
+ (CMP_WIDTH*bank_i)+ROW_WIDTH] ==
+ af_addr_r1[CS_RANGE_END:BANK_RANGE_START]) &&
+ bank_valid_r[bank_i]);
+ // asserted if row address match (no check for bank entry valid, rely
+ // on this term to be used in conjunction with BANK_HIT[])
+ row_miss[bank_i]
+ = (bank_cmp_addr_r[(CMP_WIDTH*bank_i)+ROW_WIDTH-1:
+ (CMP_WIDTH*bank_i)] !=
+ af_addr_r1[ROW_RANGE_END:ROW_RANGE_START]);
+ end
+ end
+
+ always @(posedge clk) begin
+ no_precharge_wait_r <= bank_valid_r[3] & bank_conflict_r;
+ bank_hit_r1 <= bank_hit_r;
+ end
+
+ always@(*)
+ no_precharge_r = ~bank_valid_r[3] & bank_conflict_r;
+
+ always@(posedge clk)
+ no_precharge_r1 <= no_precharge_r;
+
+
+ always @(posedge clk) begin
+ // Clear all bank valid bits during AR (i.e. since all banks get
+ // precharged during auto-refresh)
+ if ((state_r1 == CTRL_AUTO_REFRESH)) begin
+ bank_valid_r <= {OPEN_BANK_NUM{1'b0}};
+ bank_cmp_addr_r <= {(OPEN_BANK_NUM*CMP_WIDTH-1){1'b0}};
+ end else begin
+ if (state_r1 == CTRL_ACTIVE) begin
+ // 00 is always going to have the latest bank and row.
+ bank_cmp_addr_r[CMP_WIDTH-1:0]
+ <= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
+ // This indicates the bank was activated
+ bank_valid_r[0] <= 1'b1;
+
+ case ({bank_hit_r1[2:0]})
+ 3'b001: begin
+ bank_cmp_addr_r[CMP_WIDTH-1:0]
+ <= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];
+ // This indicates the bank was activated
+ bank_valid_r[0] <= 1'b1;
+ end
+ 3'b010: begin //(b0->b1)
+ bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
+ <= bank_cmp_addr_r[CMP_WIDTH-1:0];
+ bank_valid_r[1] <= bank_valid_r[0];
+ end
+ 3'b100:begin //(b0->b1, b1->b2)
+ bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
+ <= bank_cmp_addr_r[CMP_WIDTH-1:0];
+ bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
+ <= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
+ bank_valid_r[1] <= bank_valid_r[0];
+ bank_valid_r[2] <= bank_valid_r[1];
+ end
+ default: begin //(b0->b1, b1->b2, b2->b3)
+ bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
+ <= bank_cmp_addr_r[CMP_WIDTH-1:0];
+ bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
+ <= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
+ bank_cmp_addr_r[(4*CMP_WIDTH)-1:3*CMP_WIDTH]
+ <= bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH];
+ bank_valid_r[1] <= bank_valid_r[0];
+ bank_valid_r[2] <= bank_valid_r[1];
+ bank_valid_r[3] <= bank_valid_r[2];
+ end
+ endcase
+ end
+ end
+ end
+ end else begin: gen_single_bank_open // single bank option
+ always @(posedge clk) begin
+ no_precharge_r <= 1'd0;
+ no_precharge_r1 <= 1'd0;
+ no_precharge_wait_r <= 1'd0;
+ if (rst_r1)
+ sb_open_add_r <= {CMP_WIDTH{1'b0}};
+ else if (state_r == CTRL_ACTIVE)
+ sb_open_add_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];
+ end
+ end
+ endgenerate
+
+ //***************************************************************************
+ // Timing counters
+ //***************************************************************************
+
+ //*****************************************************************
+ // Write and read enable generation for PHY
+ //*****************************************************************
+
+ // write burst count. Counts from (BL/2 to 1).
+ // Also logic for controller write enable.
+ always @(posedge clk) begin
+ if (state_r == CTRL_BURST_WRITE) begin
+ wrburst_cnt_r <= BURST_LEN_DIV2;
+ end else if (wrburst_cnt_r >= 3'd1)
+ wrburst_cnt_r <= wrburst_cnt_r - 1;
+ end // always @ (posedge clk)
+
+
+ always @(posedge clk) begin
+ if (rst_r1) begin
+ ctrl_wren <= 1'b0;
+ end else if (state_r == CTRL_BURST_WRITE) begin
+ ctrl_wren <= 1'b1;
+ end else if (wrburst_wren_ok_r)
+ ctrl_wren <= 1'b0;
+ end
+
+
+ always @(posedge clk) begin
+ if ((state_r == CTRL_BURST_WRITE)
+ && (BURST_LEN_DIV2 > 2))
+ wrburst_ok_r <= 1'd0;
+ else if ((wrburst_cnt_r <= 3'd3) ||
+ (BURST_LEN_DIV2 <= 2))
+ wrburst_ok_r <= 1'b1;
+ end
+
+ // flag to check when wrburst count has reached
+ // a value of 1. This flag is used in the ctrl_wren
+ // logic
+ always @(posedge clk) begin
+ if(wrburst_cnt_r == 3'd2)
+ wrburst_wren_ok_r <=1'b1;
+ else
+ wrburst_wren_ok_r <= 1'b0;
+ end
+
+
+ // read burst count. Counts from (BL/2 to 1)
+ always @(posedge clk) begin
+ if (state_r == CTRL_BURST_READ) begin
+ rdburst_cnt_r <= BURST_LEN_DIV2;
+ end else if (rdburst_cnt_r >= 3'd1)
+ rdburst_cnt_r <= rdburst_cnt_r - 1;
+ end // always @ (posedge clk)
+
+
+ always @(posedge clk) begin
+ if (rst_r1) begin
+ ctrl_rden <= 1'b0;
+ end else if (state_r == CTRL_BURST_READ) begin
+ ctrl_rden <= 1'b1;
+ end else if (rdburst_rden_ok_r)
+ ctrl_rden <= 1'b0;
+ end
+
+ // the rd_burst_ok_r signal will be asserted one cycle later
+ // in multi chip select cases if the back to back read is to
+ // different chip selects. The cs_changed_sticky_r signal will
+ // be asserted only for multi chip select cases.
+ always @(posedge clk) begin
+ if ((state_r == CTRL_BURST_READ)
+ && (BURST_LEN_DIV2 > 2))
+ rdburst_ok_r <= 1'd0;
+ else if ((rdburst_cnt_r <=( 3'd3 - cs_change_sticky_r)) ||
+ (BURST_LEN_DIV2 <= 2))
+ rdburst_ok_r <= 1'b1;
+ end
+
+ // flag to check when rdburst count has reached
+ // a value of 1. This flag is used in the ctrl_rden
+ // logic
+ always @(posedge clk) begin
+ if (rdburst_cnt_r == 3'd2)
+ rdburst_rden_ok_r <= 1'b1;
+ else
+ rdburst_rden_ok_r <= 1'b0;
+ end
+
+
+ //*****************************************************************
+ // Various delay counters
+ // The counters are checked for value of <= 3 to determine the
+ // if the count values are reached during different commands.
+ // It is checked for 3 because
+ // 1. The counters are loaded during the state when the command
+ // state is reached (+1)
+ // 2. After the <= 3 condition is reached the sm takes two cycles
+ // to transition to the new command state (+2)
+ //*****************************************************************
+
+ // tRP count - precharge command period
+ always @(posedge clk) begin
+ if (state_r == CTRL_PRECHARGE)
+ rp_cnt_r <= TRP_COUNT;
+ else if (rp_cnt_r != 4'd0)
+ rp_cnt_r <= rp_cnt_r - 1;
+ end
+
+ always @(posedge clk) begin
+ if (state_r == CTRL_PRECHARGE)
+ rp_cnt_ok_r <= 1'd0;
+ else if (rp_cnt_r <= 4'd3)
+ rp_cnt_ok_r <= 1'd1;
+ end
+
+ // tRFC count - refresh-refresh, refresh-active
+ always @(posedge clk) begin
+ if (state_r == CTRL_AUTO_REFRESH)
+ rfc_cnt_r <= TRFC_COUNT;
+ else if (rfc_cnt_r != 8'd0)
+ rfc_cnt_r <= rfc_cnt_r - 1;
+ end
+
+ always @(posedge clk) begin
+ if (state_r == CTRL_AUTO_REFRESH)
+ rfc_ok_r <= 1'b0;
+ else if(rfc_cnt_r <= 8'd3)
+ rfc_ok_r <= 1'b1;
+ end
+
+ // tRCD count - active to read/write
+ always @(posedge clk) begin
+ if (state_r == CTRL_ACTIVE)
+ rcd_cnt_r <= TRCD_COUNT;
+ else if (rcd_cnt_r != 4'd0)
+ rcd_cnt_r <= rcd_cnt_r - 1;
+ end
+
+ always @(posedge clk) begin
+ if ((state_r == CTRL_ACTIVE)
+ && (TRCD_COUNT > 2))
+ rcd_cnt_ok_r <= 1'd0;
+ else if (rcd_cnt_r <= 4'd3)
+ rcd_cnt_ok_r <= 1;
+ end
+
+ // tRRD count - active to active
+ always @(posedge clk) begin
+ if (state_r == CTRL_ACTIVE)
+ trrd_cnt_r <= TRRD_COUNT;
+ else if (trrd_cnt_r != 3'd0)
+ trrd_cnt_r <= trrd_cnt_r - 1;
+ end
+
+ always @(posedge clk) begin
+ if (state_r == CTRL_ACTIVE)
+ trrd_cnt_ok_r <= 1'd0;
+ else if (trrd_cnt_r <= 3'd3)
+ trrd_cnt_ok_r <= 1;
+ end
+
+ // tRAS count - active to precharge
+ always @(posedge clk) begin
+ if (state_r == CTRL_ACTIVE)
+ ras_cnt_r <= TRAS_COUNT;
+ else if (ras_cnt_r != 5'd0)
+ ras_cnt_r <= ras_cnt_r - 1;
+ end
+
+ // counter for write to prcharge
+ // read to precharge and
+ // activate to precharge
+ // precharge_ok_cnt_r is added with trtp count,
+ // there can be cases where the sm can go from
+ // activate to read and the act->pre count time
+ // would not have been satisfied. The rd->pre
+ // time is very less. wr->pre time is almost the
+ // same as act-> pre
+ always @(posedge clk) begin
+ if (rst_r1)
+ precharge_ok_cnt_r <= 5'd0;
+ else if (state_r == CTRL_BURST_READ) begin
+ // assign only if the cnt is < TRTP_COUNT
+ if (precharge_ok_cnt_r < TRTP_COUNT)
+ precharge_ok_cnt_r <= TRTP_COUNT;
+ end else if (state_r == CTRL_BURST_WRITE)
+ precharge_ok_cnt_r <= TWR_COUNT;
+ else if (state_r == CTRL_ACTIVE)
+ if (precharge_ok_cnt_r <= TRAS_COUNT)
+ precharge_ok_cnt_r <= TRAS_COUNT;
+ else
+ precharge_ok_cnt_r <= precharge_ok_cnt_r - 1;
+ else if (precharge_ok_cnt_r != 5'd0)
+ precharge_ok_cnt_r <= precharge_ok_cnt_r - 1;
+ end
+
+ always @(posedge clk) begin
+ if ((state_r == CTRL_BURST_READ) ||
+ (state_r == CTRL_BURST_WRITE)||
+ (state_r == CTRL_ACTIVE))
+ precharge_ok_r <= 1'd0;
+ else if(precharge_ok_cnt_r <= 5'd3)
+ precharge_ok_r <=1'd1;
+ end
+
+ // write to read counter
+ // write to read includes : write latency + burst time + tWTR
+ always @(posedge clk) begin
+ if (rst_r1)
+ wr_to_rd_cnt_r <= 5'd0;
+ else if (state_r == CTRL_BURST_WRITE)
+ wr_to_rd_cnt_r <= (TWTR_COUNT);
+ else if (wr_to_rd_cnt_r != 5'd0)
+ wr_to_rd_cnt_r <= wr_to_rd_cnt_r - 1;
+ end
+
+ always @(posedge clk) begin
+ if (state_r == CTRL_BURST_WRITE)
+ wr_to_rd_ok_r <= 1'd0;
+ else if (wr_to_rd_cnt_r <= 5'd3)
+ wr_to_rd_ok_r <= 1'd1;
+ end
+
+ // read to write counter
+ always @(posedge clk) begin
+ if (rst_r1)
+ rd_to_wr_cnt_r <= 5'd0;
+ else if (state_r == CTRL_BURST_READ)
+ rd_to_wr_cnt_r <= (TRTW_COUNT);
+ else if (rd_to_wr_cnt_r != 5'd0)
+ rd_to_wr_cnt_r <= rd_to_wr_cnt_r - 1;
+ end
+
+ always @(posedge clk) begin
+ if (state_r == CTRL_BURST_READ)
+ rd_to_wr_ok_r <= 1'b0;
+ else if (rd_to_wr_cnt_r <= 5'd3)
+ rd_to_wr_ok_r <= 1'b1;
+ end
+
+ always @(posedge clk) begin
+ if(refi_cnt_r == (TREFI_COUNT -1))
+ refi_cnt_ok_r <= 1'b1;
+ else
+ refi_cnt_ok_r <= 1'b0;
+ end
+
+ // auto refresh interval counter in refresh_clk domain
+ always @(posedge clk) begin
+ if ((rst_r1) || (refi_cnt_ok_r)) begin
+ refi_cnt_r <= 12'd0;
+ end else begin
+ refi_cnt_r <= refi_cnt_r + 1;
+ end
+ end // always @ (posedge clk)
+
+ // auto refresh flag
+ always @(posedge clk) begin
+ if (refi_cnt_ok_r) begin
+ ref_flag_r <= 1'b1;
+ end else begin
+ ref_flag_r <= 1'b0;
+ end
+ end // always @ (posedge clk)
+
+ assign ctrl_ref_flag = ref_flag_r;
+
+ //refresh flag detect
+ //auto_ref high indicates auto_refresh requirement
+ //auto_ref is held high until auto refresh command is issued.
+ always @(posedge clk)begin
+ if (rst_r1)
+ auto_ref_r <= 1'b0;
+ else if (ref_flag_r)
+ auto_ref_r <= 1'b1;
+ else if (state_r == CTRL_AUTO_REFRESH)
+ auto_ref_r <= 1'b0;
+ end
+
+
+ // keep track of which chip selects got auto-refreshed (avoid auto-refreshing
+ // all CS's at once to avoid current spike)
+ always @(posedge clk)begin
+ if (rst_r1 || (state_r1 == CTRL_PRECHARGE))
+ auto_cnt_r <= 'd0;
+ else if (state_r1 == CTRL_AUTO_REFRESH)
+ auto_cnt_r <= auto_cnt_r + 1;
+ end
+
+ // register for timing purposes. Extra delay doesn't really matter
+ always @(posedge clk)
+ phy_init_done_r <= phy_init_done;
+
+ always @(posedge clk)begin
+ if (rst_r1) begin
+ state_r <= CTRL_IDLE;
+ state_r1 <= CTRL_IDLE;
+ end else begin
+ state_r <= next_state;
+ state_r1 <= state_r;
+ end
+ end
+
+ //***************************************************************************
+ // main control state machine
+ //***************************************************************************
+
+ always @(*) begin
+ next_state = state_r;
+ (* full_case, parallel_case *) case (state_r)
+ CTRL_IDLE: begin
+ // perform auto refresh as soon as we are done with calibration.
+ // The calibration logic does not do any refreshes.
+ if (phy_init_done_r)
+ next_state = CTRL_AUTO_REFRESH;
+ end
+
+ CTRL_PRECHARGE: begin
+ if (auto_ref_r)
+ next_state = CTRL_PRECHARGE_WAIT1;
+ // when precharging an LRU bank, do not have to go to wait state
+ // since we can't possibly be activating row in same bank next
+ // disabled for 2t timing. There needs to be a gap between cmds
+ // in 2t timing
+ else if (no_precharge_wait_r && !TWO_T_TIME_EN)
+ next_state = CTRL_ACTIVE;
+ else
+ next_state = CTRL_PRECHARGE_WAIT;
+ end
+
+ CTRL_PRECHARGE_WAIT:begin
+ if (rp_cnt_ok_r)begin
+ if (auto_ref_r)
+ // precharge again to make sure we close all the banks
+ next_state = CTRL_PRECHARGE;
+ else
+ next_state = CTRL_ACTIVE;
+ end
+ end
+
+ CTRL_PRECHARGE_WAIT1:
+ if (rp_cnt_ok_r)
+ next_state = CTRL_AUTO_REFRESH;
+
+ CTRL_AUTO_REFRESH:
+ next_state = CTRL_AUTO_REFRESH_WAIT;
+
+ CTRL_AUTO_REFRESH_WAIT:
+ //staggering Auto refresh for multi
+ // chip select designs. The SM waits
+ // for the rfc time before issuing the
+ // next auto refresh.
+ if (auto_cnt_r < (CS_NUM))begin
+ if (rfc_ok_r )
+ next_state = CTRL_AUTO_REFRESH;
+ end else if (rfc_ok_r)begin
+ if(auto_ref_r)
+ // MIG 2.3: For deep designs if Auto Refresh
+ // flag asserted immediately after calibration is completed
+ next_state = CTRL_PRECHARGE;
+ else if ( wr_flag || rd_flag)
+ next_state = CTRL_ACTIVE;
+ end
+
+ CTRL_ACTIVE:
+ next_state = CTRL_ACTIVE_WAIT;
+
+ CTRL_ACTIVE_WAIT: begin
+ if (rcd_cnt_ok_r) begin
+ if ((conflict_detect_r && ~conflict_resolved_r) ||
+ auto_ref_r) begin
+ if (no_precharge_r1 && ~auto_ref_r && trrd_cnt_ok_r)
+ next_state = CTRL_ACTIVE;
+ else if(precharge_ok_r)
+ next_state = CTRL_PRECHARGE;
+ end else if ((wr_flag_r) && (rd_to_wr_ok_r))
+ next_state = CTRL_BURST_WRITE;
+ else if ((rd_flag_r)&& (wr_to_rd_ok_r))
+ next_state = CTRL_BURST_READ;
+ end
+ end
+
+ // beginning of write burst
+ CTRL_BURST_WRITE: begin
+ if (BURST_LEN_DIV2 == 1) begin
+ // special case if BL = 2 (i.e. burst lasts only one clk cycle)
+ if (wr_flag)
+ // if we have another non-conflict write command right after the
+ // current write, then stay in this state
+ next_state = CTRL_BURST_WRITE;
+ else
+ // otherwise, if we're done with this burst, and have no write
+ // immediately scheduled after this one, wait until write-read
+ // delay has passed
+ next_state = CTRL_WRITE_WAIT;
+ end else
+ // otherwise BL > 2, and we have at least one more write cycle for
+ // current burst
+ next_state = CTRL_WRITE_WAIT;
+ // continuation of write burst (also covers waiting after write burst
+ // has completed for write-read delay to pass)
+ end
+
+ CTRL_WRITE_WAIT: begin
+ if ((conflict_detect) || auto_ref_r) begin
+ if (no_precharge_r && ~auto_ref_r && wrburst_ok_r)
+ next_state = CTRL_ACTIVE;
+ else if (precharge_ok_r)
+ next_state = CTRL_PRECHARGE;
+ end else if (wrburst_ok_r && wr_flag)
+ next_state = CTRL_BURST_WRITE;
+ else if ((rd_flag) && (wr_to_rd_ok_r))
+ next_state = CTRL_BURST_READ;
+ end
+
+ CTRL_BURST_READ: begin
+ if (BURST_LEN_DIV2 == 1) begin
+ // special case if BL = 2 (i.e. burst lasts only one clk cycle)
+ if (rd_flag)
+ next_state = CTRL_BURST_READ;
+ else
+ next_state = CTRL_READ_WAIT;
+ end else
+ next_state = CTRL_READ_WAIT;
+ end
+
+ CTRL_READ_WAIT: begin
+ if ((conflict_detect) || auto_ref_r)begin
+ if (no_precharge_r && ~auto_ref_r && rdburst_ok_r)
+ next_state = CTRL_ACTIVE;
+ else if (precharge_ok_r)
+ next_state = CTRL_PRECHARGE;
+ // for burst of 4 in multi chip select
+ // if there is a change in cs wait one cycle before the
+ // next read command. cs_change_r will be asserted.
+ end else if (rdburst_ok_r && rd_flag && ~cs_change_r)
+ next_state = CTRL_BURST_READ;
+ else if (wr_flag && (rd_to_wr_ok_r))
+ next_state = CTRL_BURST_WRITE;
+ end
+ endcase
+ end
+
+ //***************************************************************************
+ // control signals to memory
+ //***************************************************************************
+
+ always @(posedge clk) begin
+ if ((state_r == CTRL_AUTO_REFRESH) ||
+ (state_r == CTRL_ACTIVE) ||
+ (state_r == CTRL_PRECHARGE)) begin
+ ddr_ras_n_r <= 1'b0;
+ two_t_enable_r[0] <= 1'b0;
+ end else begin
+ if (TWO_T_TIME_EN)
+ ddr_ras_n_r <= two_t_enable_r[0] ;
+ else
+ ddr_ras_n_r <= 1'd1;
+ two_t_enable_r[0] <= 1'b1;
+ end
+ end
+
+ always @(posedge clk)begin
+ if ((state_r == CTRL_BURST_WRITE) ||
+ (state_r == CTRL_BURST_READ) ||
+ (state_r == CTRL_AUTO_REFRESH)) begin
+ ddr_cas_n_r <= 1'b0;
+ two_t_enable_r[1] <= 1'b0;
+ end else begin
+ if (TWO_T_TIME_EN)
+ ddr_cas_n_r <= two_t_enable_r[1];
+ else
+ ddr_cas_n_r <= 1'b1;
+ two_t_enable_r[1] <= 1'b1;
+ end
+ end
+
+ always @(posedge clk) begin
+ if ((state_r == CTRL_BURST_WRITE) ||
+ (state_r == CTRL_PRECHARGE)) begin
+ ddr_we_n_r <= 1'b0;
+ two_t_enable_r[2] <= 1'b0;
+ end else begin
+ if(TWO_T_TIME_EN)
+ ddr_we_n_r <= two_t_enable_r[2];
+ else
+ ddr_we_n_r <= 1'b1;
+ two_t_enable_r[2] <= 1'b1;
+ end
+ end
+
+ // turn off auto-precharge when issuing commands (A10 = 0)
+ // mapping the col add for linear addressing.
+ generate
+ if (TWO_T_TIME_EN) begin: gen_addr_col_two_t
+ if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0
+ assign ddr_addr_col = {af_addr_r3[COL_WIDTH-1:10], 1'b0,
+ af_addr_r3[9:0]};
+ end else begin
+ if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1
+ assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
+ af_addr_r3[COL_WIDTH-1:10], 1'b0,
+ af_addr_r3[9:0]};
+ end else begin: gen_ddr_addr_col_2
+ assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
+ af_addr_r3[COL_WIDTH-1:0]};
+ end
+ end
+ end else begin: gen_addr_col_one_t
+ if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0_1
+ assign ddr_addr_col = {af_addr_r2[COL_WIDTH-1:10], 1'b0,
+ af_addr_r2[9:0]};
+ end else begin
+ if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1_1
+ assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
+ af_addr_r2[COL_WIDTH-1:10], 1'b0,
+ af_addr_r2[9:0]};
+ end else begin: gen_ddr_addr_col_2_1
+ assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
+ af_addr_r2[COL_WIDTH-1:0]};
+ end
+ end
+ end
+ endgenerate
+
+ // Assign address during row activate
+ generate
+ if (TWO_T_TIME_EN)
+ assign ddr_addr_row = af_addr_r3[ROW_RANGE_END:ROW_RANGE_START];
+ else
+ assign ddr_addr_row = af_addr_r2[ROW_RANGE_END:ROW_RANGE_START];
+ endgenerate
+
+
+ always @(posedge clk)begin
+ if ((state_r == CTRL_ACTIVE) ||
+ ((state_r1 == CTRL_ACTIVE) && TWO_T_TIME_EN))
+ ddr_addr_r <= ddr_addr_row;
+ else if ((state_r == CTRL_BURST_WRITE) ||
+ (state_r == CTRL_BURST_READ) ||
+ (((state_r1 == CTRL_BURST_WRITE) ||
+ (state_r1 == CTRL_BURST_READ)) &&
+ TWO_T_TIME_EN))
+ ddr_addr_r <= ddr_addr_col;
+ else if (((state_r == CTRL_PRECHARGE) ||
+ ((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
+ && auto_ref_r) begin
+ // if we're precharging as a result of AUTO-REFRESH, precharge all banks
+ ddr_addr_r <= {ROW_WIDTH{1'b0}};
+ ddr_addr_r[10] <= 1'b1;
+ end else if ((state_r == CTRL_PRECHARGE) ||
+ ((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN))
+ // if we're precharging to close a specific bank/row, set A10=0
+ ddr_addr_r <= {ROW_WIDTH{1'b0}};
+ else
+ ddr_addr_r <= {ROW_WIDTH{1'bx}};
+ end
+
+ always @(posedge clk)begin
+ // whenever we're precharging, we're either: (1) precharging all banks (in
+ // which case banks bits are don't care, (2) precharging the LRU bank,
+ // b/c we've exceeded the limit of # of banks open (need to close the LRU
+ // bank to make room for a new one), (3) we haven't exceed the maximum #
+ // of banks open, but we trying to open a different row in a bank that's
+ // already open
+ if (((state_r == CTRL_PRECHARGE) ||
+ ((state_r1 == CTRL_PRECHARGE) && TWO_T_TIME_EN)) &&
+ bank_conflict_r && MULTI_BANK_EN)
+ // When LRU bank needs to be closed
+ ddr_ba_r <= bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_BANK_RANGE_END:
+ (3*CMP_WIDTH)+CMP_BANK_RANGE_START];
+ else begin
+ // Either precharge due to refresh or bank hit case
+ if (TWO_T_TIME_EN)
+ ddr_ba_r <= af_addr_r3[BANK_RANGE_END:BANK_RANGE_START];
+ else
+ ddr_ba_r <= af_addr_r2[BANK_RANGE_END:BANK_RANGE_START];
+ end
+ end
+
+ // chip enable generation logic
+ generate
+ // if only one chip select, always assert it after reset
+ if (CS_BITS == 0) begin: gen_ddr_cs_0
+ always @(posedge clk)
+ if (rst_r1)
+ ddr_cs_n_r[0] <= 1'b1;
+ else
+ ddr_cs_n_r[0] <= 1'b0;
+ // otherwise if we have multiple chip selects
+ end else begin: gen_ddr_cs_1
+ if(TWO_T_TIME_EN) begin: gen_2t_cs
+ always @(posedge clk)
+ if (rst_r1)
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ else if ((state_r1 == CTRL_AUTO_REFRESH)) begin
+ // if auto-refreshing, only auto-refresh one CS at any time (avoid
+ // beating on the ground plane by refreshing all CS's at same time)
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ ddr_cs_n_r[auto_cnt_r] <= 1'b0;
+ end else if (auto_ref_r && (state_r1 == CTRL_PRECHARGE)) begin
+ ddr_cs_n_r <= {CS_NUM{1'b0}};
+ end else if ((state_r1 == CTRL_PRECHARGE) && ( bank_conflict_r
+ && MULTI_BANK_EN))begin
+ // precharging the LRU bank
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
+ (3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
+ end else begin
+ // otherwise, check the upper address bits to see which CS to assert
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ ddr_cs_n_r[af_addr_r3[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
+ end // else: !if(((state_r == CTRL_PRECHARGE) ||...
+ end else begin: gen_1t_cs // block: gen_2t_cs
+ always @(posedge clk)
+ if (rst_r1)
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ else if ((state_r == CTRL_AUTO_REFRESH) ) begin
+ // if auto-refreshing, only auto-refresh one CS at any time (avoid
+ // beating on the ground plane by refreshing all CS's at same time)
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ ddr_cs_n_r[auto_cnt_r] <= 1'b0;
+ end else if (auto_ref_r && (state_r == CTRL_PRECHARGE) ) begin
+ ddr_cs_n_r <= {CS_NUM{1'b0}};
+ end else if ((state_r == CTRL_PRECHARGE) &&
+ (bank_conflict_r && MULTI_BANK_EN))begin
+ // precharging the LRU bank
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
+ (3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
+ end else begin
+ // otherwise, check the upper address bits to see which CS to assert
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ ddr_cs_n_r[af_addr_r2[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
+ end // else: !if(((state_r == CTRL_PRECHARGE) ||...
+ end // block: gen_1t_cs
+ end
+ endgenerate
+
+ // registring the two_t timing enable signal.
+ // This signal will be asserted (low) when the
+ // chip select has to be asserted.
+ always @(posedge clk)begin
+ if(&two_t_enable_r)
+ two_t_enable_r1 <= {CS_NUM{1'b1}};
+ else
+ two_t_enable_r1 <= {CS_NUM{1'b0}};
+ end
+
+ assign ctrl_addr = ddr_addr_r;
+ assign ctrl_ba = ddr_ba_r;
+ assign ctrl_ras_n = ddr_ras_n_r;
+ assign ctrl_cas_n = ddr_cas_n_r;
+ assign ctrl_we_n = ddr_we_n_r;
+ assign ctrl_cs_n = (TWO_T_TIME_EN) ?
+ (ddr_cs_n_r | two_t_enable_r1) :
+ ddr_cs_n_r;
+
+endmodule
+
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_addr_fifo.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_addr_fifo.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_addr_fifo.v (revision 3)
@@ -0,0 +1,131 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_usr_addr_fifo.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Mon Aug 28 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module instantiates the block RAM based FIFO to store the user
+// address and the command information. Also calculates potential bank/row
+// conflicts by comparing the new address with last address issued.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_usr_addr_fifo #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter COL_WIDTH = 10,
+ parameter CS_BITS = 0,
+ parameter ROW_WIDTH = 14
+ )
+ (
+ input clk0,
+ input rst0,
+ input [2:0] app_af_cmd,
+ input [30:0] app_af_addr,
+ input app_af_wren,
+ input ctrl_af_rden,
+ output [2:0] af_cmd,
+ output [30:0] af_addr,
+ output af_empty,
+ output app_af_afull
+ );
+
+ wire [35:0] fifo_data_out;
+ reg rst_r;
+
+
+ always @(posedge clk0)
+ rst_r <= rst0;
+
+
+ //***************************************************************************
+
+ assign af_cmd = fifo_data_out[33:31];
+ assign af_addr = fifo_data_out[30:0];
+
+ //***************************************************************************
+
+ FIFO36 #
+ (
+ .ALMOST_EMPTY_OFFSET (13'h0007),
+ .ALMOST_FULL_OFFSET (13'h000F),
+ .DATA_WIDTH (36),
+ .DO_REG (1),
+ .EN_SYN ("TRUE"),
+ .FIRST_WORD_FALL_THROUGH ("FALSE")
+ )
+ u_af
+ (
+ .ALMOSTEMPTY (),
+ .ALMOSTFULL (app_af_afull),
+ .DO (fifo_data_out[31:0]),
+ .DOP (fifo_data_out[35:32]),
+ .EMPTY (af_empty),
+ .FULL (),
+ .RDCOUNT (),
+ .RDERR (),
+ .WRCOUNT (),
+ .WRERR (),
+ .DI ({app_af_cmd[0],app_af_addr}),
+ .DIP ({2'b00,app_af_cmd[2:1]}),
+ .RDCLK (clk0),
+ .RDEN (ctrl_af_rden),
+ .RST (rst_r),
+ .WRCLK (clk0),
+ .WREN (app_af_wren)
+ );
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_dm_iob.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_dm_iob.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_dm_iob.v (revision 3)
@@ -0,0 +1,106 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_phy_dm_iob.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module places the data mask signals into the IOBs.
+//Reference:
+//Revision History:
+// Rev 1.1 - To fix timing issues with Synplicity 9.6.1, syn_preserve
+// attribute added for the instance u_dm_ce. PK. 11/11/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_dm_iob
+ (
+ input clk90,
+ input dm_ce,
+ input mask_data_rise,
+ input mask_data_fall,
+ output ddr_dm
+ );
+
+ wire dm_out;
+ wire dm_ce_r;
+
+ FDRSE_1 u_dm_ce
+ (
+ .Q (dm_ce_r),
+ .C (clk90),
+ .CE (1'b1),
+ .D (dm_ce),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve=1 */;
+
+ ODDR #
+ (
+ .SRTYPE("SYNC"),
+ .DDR_CLK_EDGE("SAME_EDGE")
+ )
+ u_oddr_dm
+ (
+ .Q (dm_out),
+ .C (clk90),
+ .CE (dm_ce_r),
+ .D1 (mask_data_rise),
+ .D2 (mask_data_fall),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ OBUF u_obuf_dm
+ (
+ .I (dm_out),
+ .O (ddr_dm)
+ );
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_write.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_write.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_write.v (revision 3)
@@ -0,0 +1,469 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_phy_write.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Thu Aug 24 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//Reference:
+// Handles delaying various write control signals appropriately depending
+// on CAS latency, additive latency, etc. Also splits the data and mask in
+// rise and fall buses.
+//Revision History:
+// Rev 1.1 - For Dual Rank parts support ODT logic corrected. PK. 08/05/08
+// Rev 1.2 - Retain current data pattern for stage 4 calibration, and create
+// new pattern for stage 4. RC. 09/21/09.
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_write #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter DQ_WIDTH = 72,
+ parameter CS_NUM = 1,
+ parameter ADDITIVE_LAT = 0,
+ parameter CAS_LAT = 5,
+ parameter ECC_ENABLE = 0,
+ parameter ODT_TYPE = 1,
+ parameter REG_ENABLE = 1,
+ parameter DDR_TYPE = 1
+ )
+ (
+ input clk0,
+ input clk90,
+ input rst90,
+ input [(2*DQ_WIDTH)-1:0] wdf_data,
+ input [(2*DQ_WIDTH/8)-1:0] wdf_mask_data,
+ input ctrl_wren,
+ input phy_init_wren,
+ input phy_init_data_sel,
+ output reg dm_ce,
+ output reg [1:0] dq_oe_n,
+ output reg dqs_oe_n ,
+ output reg dqs_rst_n ,
+ output wdf_rden,
+ output reg [CS_NUM-1:0] odt ,
+ output [DQ_WIDTH-1:0] wr_data_rise,
+ output [DQ_WIDTH-1:0] wr_data_fall,
+ output [(DQ_WIDTH/8)-1:0] mask_data_rise,
+ output [(DQ_WIDTH/8)-1:0] mask_data_fall
+ );
+
+ localparam MASK_WIDTH = DQ_WIDTH/8;
+ localparam DDR1 = 0;
+ localparam DDR2 = 1;
+ localparam DDR3 = 2;
+
+ // (MIN,MAX) value of WR_LATENCY for DDR1:
+ // REG_ENABLE = (0,1)
+ // ECC_ENABLE = (0,1)
+ // Write latency = 1
+ // Total: (1,3)
+ // (MIN,MAX) value of WR_LATENCY for DDR2:
+ // REG_ENABLE = (0,1)
+ // ECC_ENABLE = (0,1)
+ // Write latency = ADDITIVE_CAS + CAS_LAT - 1 = (0,4) + (3,5) - 1 = (2,8)
+ // ADDITIVE_LAT = (0,4) (JEDEC79-2B)
+ // CAS_LAT = (3,5) (JEDEC79-2B)
+ // Total: (2,10)
+ localparam WR_LATENCY = (DDR_TYPE == DDR3) ?
+ (ADDITIVE_LAT + (CAS_LAT) + REG_ENABLE ) :
+ (DDR_TYPE == DDR2) ?
+ (ADDITIVE_LAT + (CAS_LAT-1) + REG_ENABLE ) :
+ (1 + REG_ENABLE );
+
+ // NOTE that ODT timing does not need to be delayed for registered
+ // DIMM case, since like other control/address signals, it gets
+ // delayed by one clock cycle at the DIMM
+ localparam ODT_WR_LATENCY = WR_LATENCY - REG_ENABLE;
+
+ wire dm_ce_0;
+ reg dm_ce_r;
+ wire [1:0] dq_oe_0;
+ reg [1:0] dq_oe_n_90_r1;
+ reg [1:0] dq_oe_270;
+ wire dqs_oe_0;
+ reg dqs_oe_270;
+ reg dqs_oe_n_180_r1;
+ wire dqs_rst_0;
+ reg dqs_rst_n_180_r1;
+ reg dqs_rst_270;
+ reg ecc_dm_error_r;
+ reg ecc_dm_error_r1;
+ reg [(DQ_WIDTH-1):0] init_data_f;
+ reg [(DQ_WIDTH-1):0] init_data_r;
+ reg [3:0] init_wdf_cnt_r;
+ wire odt_0;
+ reg rst90_r /* synthesis syn_maxfan = 10 */;
+ reg [10:0] wr_stages ;
+ reg [(2*DQ_WIDTH)-1:0] wdf_data_r;
+ reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r;
+ wire [(2*DQ_WIDTH/8)-1:0] wdf_ecc_mask;
+
+ reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r1;
+ wire wdf_rden_0;
+ reg calib_rden_90_r;
+ reg wdf_rden_90_r;
+ reg wdf_rden_90_r1;
+ reg wdf_rden_270;
+
+ always @(posedge clk90)
+ rst90_r <= rst90;
+
+ //***************************************************************************
+ // Analysis of additional pipeline delays:
+ // 1. dq_oe (DQ 3-state): 1 CLK90 cyc in IOB 3-state FF
+ // 2. dqs_oe (DQS 3-state): 1 CLK180 cyc in IOB 3-state FF
+ // 3. dqs_rst (DQS output value reset): 1 CLK180 cyc in FF + 1 CLK180 cyc
+ // in IOB DDR
+ // 4. odt (ODT control): 1 CLK0 cyc in IOB FF
+ // 5. write data (output two cyc after wdf_rden - output of RAMB_FIFO w/
+ // output register enabled): 2 CLK90 cyc in OSERDES
+ //***************************************************************************
+
+ // DQS 3-state must be asserted one extra clock cycle due b/c of write
+ // pre- and post-amble (extra half clock cycle for each)
+ assign dqs_oe_0 = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
+
+ // same goes for ODT, need to handle both pre- and post-amble (generate
+ // ODT only for DDR2)
+ // ODT generation for DDR2 based on write latency. The MIN write
+ // latency is 2. Based on the write latency ODT is asserted.
+ generate
+ if ((DDR_TYPE != DDR1) && (ODT_TYPE > 0))begin: gen_odt_ddr2
+ if(ODT_WR_LATENCY > 3)
+ assign odt_0 =
+ wr_stages[ODT_WR_LATENCY-2] |
+ wr_stages[ODT_WR_LATENCY-3] |
+ wr_stages[ODT_WR_LATENCY-4] ;
+ else if ( ODT_WR_LATENCY == 3)
+ assign odt_0 =
+ wr_stages[ODT_WR_LATENCY-1] |
+ wr_stages[ODT_WR_LATENCY-2] |
+ wr_stages[ODT_WR_LATENCY-3] ;
+ else
+ assign odt_0 =
+ wr_stages[ODT_WR_LATENCY] |
+ wr_stages[ODT_WR_LATENCY-1] |
+ wr_stages[ODT_WR_LATENCY-2] ;
+ end else
+ assign odt_0 = 1'b0;
+ endgenerate
+
+ assign dq_oe_0[0] = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY];
+ assign dq_oe_0[1] = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
+ assign dqs_rst_0 = ~wr_stages[WR_LATENCY-2];
+ assign dm_ce_0 = wr_stages[WR_LATENCY] | wr_stages[WR_LATENCY-1]
+ | wr_stages[WR_LATENCY-2];
+
+ // write data fifo, read flag assertion
+ generate
+ if (DDR_TYPE != DDR1) begin: gen_wdf_ddr2
+ if (WR_LATENCY > 2)
+ assign wdf_rden_0 = wr_stages[WR_LATENCY-3];
+ else
+ assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
+ end else begin: gen_wdf_ddr1
+ assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
+ end
+ endgenerate
+
+ // first stage isn't registered
+ always @(*)
+ wr_stages[0] = (phy_init_data_sel) ? ctrl_wren : phy_init_wren;
+
+ always @(posedge clk0) begin
+ wr_stages[1] <= wr_stages[0];
+ wr_stages[2] <= wr_stages[1];
+ wr_stages[3] <= wr_stages[2];
+ wr_stages[4] <= wr_stages[3];
+ wr_stages[5] <= wr_stages[4];
+ wr_stages[6] <= wr_stages[5];
+ wr_stages[7] <= wr_stages[6];
+ wr_stages[8] <= wr_stages[7];
+ wr_stages[9] <= wr_stages[8];
+ wr_stages[10] <= wr_stages[9];
+ end
+
+ // intermediate synchronization to CLK270
+ always @(negedge clk90) begin
+ dq_oe_270 <= dq_oe_0;
+ dqs_oe_270 <= dqs_oe_0;
+ dqs_rst_270 <= dqs_rst_0;
+ wdf_rden_270 <= wdf_rden_0;
+ end
+
+ // synchronize DQS signals to CLK180
+ always @(negedge clk0) begin
+ dqs_oe_n_180_r1 <= ~dqs_oe_270;
+ dqs_rst_n_180_r1 <= ~dqs_rst_270;
+ end
+
+ // All write data-related signals synced to CLK90
+ always @(posedge clk90) begin
+ dq_oe_n_90_r1 <= ~dq_oe_270;
+ wdf_rden_90_r <= wdf_rden_270;
+ end
+
+ // generate for wdf_rden and calib rden. These signals
+ // are asserted based on write latency. For write
+ // latency of 2, the extra register stage is taken out.
+ generate
+ if (WR_LATENCY > 2) begin
+ always @(posedge clk90) begin
+ // assert wdf rden only for non calibration opertations
+ wdf_rden_90_r1 <= wdf_rden_90_r &
+ phy_init_data_sel;
+ // rden for calibration
+ calib_rden_90_r <= wdf_rden_90_r;
+ end
+ end else begin
+ always @(*) begin
+ wdf_rden_90_r1 = wdf_rden_90_r
+ & phy_init_data_sel;
+ calib_rden_90_r = wdf_rden_90_r;
+ end
+ end // else: !if(WR_LATENCY > 2)
+ endgenerate
+
+ // dm CE signal to stop dm oscilation
+ always @(negedge clk90)begin
+ dm_ce_r <= dm_ce_0;
+ dm_ce <= dm_ce_r;
+ end
+
+ // When in ECC mode the upper byte [71:64] will have the
+ // ECC parity. Mapping the bytes which have valid data
+ // to the upper byte in ecc mode. Also in ecc mode there
+ // is an extra register stage to account for timing.
+
+ genvar mask_i;
+ generate
+ if(ECC_ENABLE) begin
+ for (mask_i = 0; mask_i < (2*DQ_WIDTH)/72;
+ mask_i = mask_i+1) begin: gen_mask
+ assign wdf_ecc_mask[((mask_i*9)+9)-1:(mask_i*9)] =
+ {&wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9],
+ wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9]};
+ end
+ end
+ endgenerate
+
+ generate
+ if (ECC_ENABLE) begin:gen_ecc_reg
+ always @(posedge clk90)begin
+ if(phy_init_data_sel)
+ wdf_mask_r <= wdf_ecc_mask;
+ else
+ wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
+ end
+ end else begin
+ always@(posedge clk90) begin
+ if (phy_init_data_sel)
+ wdf_mask_r <= wdf_mask_data;
+ else
+ wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
+ end
+ end
+ endgenerate
+
+ always @(posedge clk90) begin
+ if(phy_init_data_sel)
+ wdf_data_r <= wdf_data;
+ else
+ wdf_data_r <={init_data_f,init_data_r};
+ end
+
+ // Error generation block during simulation.
+ // Error will be displayed when all the DM
+ // bits are not zero. The error will be
+ // displayed only during the start of the sequence
+ // for errors that are continous over many cycles.
+ generate
+ if (ECC_ENABLE) begin: gen_ecc_error
+ always @(posedge clk90) begin
+ //synthesis translate_off
+ wdf_mask_r1 <= wdf_mask_r;
+ if(DQ_WIDTH > 72)
+ ecc_dm_error_r
+ <= (
+ (~wdf_mask_r1[35] && (|wdf_mask_r1[34:27])) ||
+ (~wdf_mask_r1[26] && (|wdf_mask_r1[25:18])) ||
+ (~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
+ (~wdf_mask_r1[8] && (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
+ else
+ ecc_dm_error_r
+ <= ((~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
+ (~wdf_mask_r1[8] && (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
+ ecc_dm_error_r1 <= ecc_dm_error_r ;
+ if (ecc_dm_error_r && ~ecc_dm_error_r1) // assert the error only once.
+ $display ("ECC DM ERROR. ");
+ //synthesis translate_on
+ end
+ end
+ endgenerate
+
+ //***************************************************************************
+ // State logic to write calibration training patterns
+ //***************************************************************************
+
+ always @(posedge clk90) begin
+ if (rst90_r) begin
+ init_wdf_cnt_r <= 4'd0;
+ init_data_r <= {64{1'bx}};
+ init_data_f <= {64{1'bx}};
+ end else begin
+ init_wdf_cnt_r <= init_wdf_cnt_r + calib_rden_90_r;
+ casex (init_wdf_cnt_r)
+ // First stage calibration. Pattern (rise/fall) = 1(r)->0(f)
+ // The rise data and fall data are already interleaved in the manner
+ // required for data into the WDF write FIFO
+ 4'b00xx: begin
+ init_data_r <= {DQ_WIDTH{1'b1}};
+ init_data_f <= {DQ_WIDTH{1'b0}};
+ end
+ // Second stage calibration. Pattern = 1(r)->1(f)->0(r)->0(f)
+ 4'b01x0: begin
+ init_data_r <= {DQ_WIDTH{1'b1}};
+ init_data_f <= {DQ_WIDTH{1'b1}};
+ end
+ 4'b01x1: begin
+ init_data_r <= {DQ_WIDTH{1'b0}};
+ init_data_f <= {DQ_WIDTH{1'b0}};
+ end
+ // MIG 3.2: Changed Stage 3/4 training pattern
+ // Third stage calibration patern =
+ // 11(r)->ee(f)->ee(r)->11(f)-ee(r)->11(f)->ee(r)->11(f)
+ 4'b1000: begin
+ init_data_r <= {DQ_WIDTH/4{4'h1}};
+ init_data_f <= {DQ_WIDTH/4{4'hE}};
+ end
+ 4'b1001: begin
+ init_data_r <= {DQ_WIDTH/4{4'hE}};
+ init_data_f <= {DQ_WIDTH/4{4'h1}};
+ end
+ 4'b1010: begin
+ init_data_r <= {(DQ_WIDTH/4){4'hE}};
+ init_data_f <= {(DQ_WIDTH/4){4'h1}};
+ end
+ 4'b1011: begin
+ init_data_r <= {(DQ_WIDTH/4){4'hE}};
+ init_data_f <= {(DQ_WIDTH/4){4'h1}};
+ end
+ // Fourth stage calibration patern =
+ // 11(r)->ee(f)->ee(r)->11(f)-11(r)->ee(f)->ee(r)->11(f)
+ 4'b1100: begin
+ init_data_r <= {DQ_WIDTH/4{4'h1}};
+ init_data_f <= {DQ_WIDTH/4{4'hE}};
+ end
+ 4'b1101: begin
+ init_data_r <= {DQ_WIDTH/4{4'hE}};
+ init_data_f <= {DQ_WIDTH/4{4'h1}};
+ end
+ 4'b1110: begin
+ init_data_r <= {(DQ_WIDTH/4){4'h1}};
+ init_data_f <= {(DQ_WIDTH/4){4'hE}};
+ end
+ 4'b1111: begin
+ // MIG 3.5: Corrected last two writes for stage 4 calibration
+ // training pattern. Previously MIG 3.3 and MIG 3.4 had the
+ // incorrect pattern. This can sometimes result in a calibration
+ // point with small timing margin.
+// init_data_r <= {(DQ_WIDTH/4){4'h1}};
+// init_data_f <= {(DQ_WIDTH/4){4'hE}};
+ init_data_r <= {(DQ_WIDTH/4){4'hE}};
+ init_data_f <= {(DQ_WIDTH/4){4'h1}};
+ end
+ endcase
+ end
+ end
+
+ //***************************************************************************
+
+ always @(posedge clk90)
+ dq_oe_n <= dq_oe_n_90_r1;
+
+ always @(negedge clk0)
+ dqs_oe_n <= dqs_oe_n_180_r1;
+
+ always @(negedge clk0)
+ dqs_rst_n <= dqs_rst_n_180_r1;
+
+ // generate for odt. odt is asserted based on
+ // write latency. For write latency of 2
+ // the extra register stage is taken out.
+ generate
+ if (ODT_WR_LATENCY > 3) begin
+ always @(posedge clk0) begin
+ odt <= 'b0;
+ odt[0] <= odt_0;
+ end
+ end else begin
+ always @ (*) begin
+ odt = 'b0;
+ odt[0] = odt_0;
+ end
+ end
+ endgenerate
+
+ assign wdf_rden = wdf_rden_90_r1;
+
+ //***************************************************************************
+ // Format write data/mask: Data is in format: {fall, rise}
+ //***************************************************************************
+
+ assign wr_data_rise = wdf_data_r[DQ_WIDTH-1:0];
+ assign wr_data_fall = wdf_data_r[(2*DQ_WIDTH)-1:DQ_WIDTH];
+ assign mask_data_rise = wdf_mask_r[MASK_WIDTH-1:0];
+ assign mask_data_fall = wdf_mask_r[(2*MASK_WIDTH)-1:MASK_WIDTH];
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_dq_iob.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_dq_iob.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_dq_iob.v (revision 3)
@@ -0,0 +1,592 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_phy_dq_iob.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module places the data in the IOBs.
+//Reference:
+//Revision History:
+// Rev 1.1 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
+// Rev 1.2 - DIRT strings removed and modified the code. PK. 11/13/08
+// Rev 1.3 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
+// on IODELAY primitive. PK. 11/27/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_dq_iob #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter HIGH_PERFORMANCE_MODE = "TRUE",
+ parameter IODELAY_GRP = "IODELAY_MIG",
+ parameter FPGA_SPEED_GRADE = 2
+ )
+ (
+ input clk0,
+ input clk90,
+ input clkdiv0,
+ input rst90,
+ input dlyinc,
+ input dlyce,
+ input dlyrst,
+ input [1:0] dq_oe_n,
+ input dqs,
+ input ce,
+ input rd_data_sel,
+ input wr_data_rise,
+ input wr_data_fall,
+ output rd_data_rise,
+ output rd_data_fall,
+ inout ddr_dq
+ );
+
+ wire dq_iddr_clk;
+ wire dq_idelay;
+ wire dq_in;
+ wire dq_oe_n_r;
+ wire dq_out;
+ wire stg2a_out_fall;
+ wire stg2a_out_rise;
+ (* XIL_PAR_DELAY = "0 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
+ wire stg2b_out_fall;
+ (* XIL_PAR_DELAY = "0 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
+ wire stg2b_out_rise;
+ wire stg3a_out_fall;
+ wire stg3a_out_rise;
+ wire stg3b_out_fall;
+ wire stg3b_out_rise;
+
+ //***************************************************************************
+ // Directed routing constraints for route between IDDR and stage 2 capture
+ // in fabric.
+ // Only 2 out of the 12 wire declarations will be used for any given
+ // instantiation of this module.
+ // Varies according:
+ // (1) I/O column (left, center, right) used
+ // (2) Which I/O in I/O pair (master, slave) used
+ // Nomenclature: _Xy, X = column (0 = left, 1 = center, 2 = right),
+ // y = master or slave
+ //***************************************************************************
+
+ // MODIFIED, RC, 06/13/08: Remove all references to DIRT, master/slave
+
+ (* XIL_PAR_DELAY = "515 ps", XIL_PAR_SKEW = "55 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
+ wire stg1_out_rise_sg3;
+ (* XIL_PAR_DELAY = "515 ps", XIL_PAR_SKEW = "55 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
+ wire stg1_out_fall_sg3;
+ (* XIL_PAR_DELAY = "575 ps", XIL_PAR_SKEW = "65 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
+ wire stg1_out_rise_sg2;
+ (* XIL_PAR_DELAY = "575 ps", XIL_PAR_SKEW = "65 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
+ wire stg1_out_fall_sg2;
+ (* XIL_PAR_DELAY = "650 ps", XIL_PAR_SKEW = "70 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
+ wire stg1_out_rise_sg1;
+ (* XIL_PAR_DELAY = "650 ps", XIL_PAR_SKEW = "70 ps", XIL_PAR_IP_NAME = "MIG", syn_keep = "1", keep = "TRUE" *)
+ wire stg1_out_fall_sg1;
+
+ //***************************************************************************
+ // Bidirectional I/O
+ //***************************************************************************
+
+ IOBUF u_iobuf_dq
+ (
+ .I (dq_out),
+ .T (dq_oe_n_r),
+ .IO (ddr_dq),
+ .O (dq_in)
+ );
+
+ //***************************************************************************
+ // Write (output) path
+ //***************************************************************************
+
+ // on a write, rising edge of DQS corresponds to rising edge of CLK180
+ // (aka falling edge of CLK0 -> rising edge DQS). We also know:
+ // 1. data must be driven 1/4 clk cycle before corresponding DQS edge
+ // 2. first rising DQS edge driven on falling edge of CLK0
+ // 3. rising data must be driven 1/4 cycle before falling edge of CLK0
+ // 4. therefore, rising data driven on rising edge of CLK
+ ODDR #
+ (
+ .SRTYPE("SYNC"),
+ .DDR_CLK_EDGE("SAME_EDGE")
+ )
+ u_oddr_dq
+ (
+ .Q (dq_out),
+ .C (clk90),
+ .CE (1'b1),
+ .D1 (wr_data_rise),
+ .D2 (wr_data_fall),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ // make sure output is tri-state during reset (DQ_OE_N_R = 1)
+ ODDR #
+ (
+ .SRTYPE("ASYNC"),
+ .DDR_CLK_EDGE("SAME_EDGE")
+ )
+ u_tri_state_dq
+ (
+ .Q (dq_oe_n_r),
+ .C (clk90),
+ .CE (1'b1),
+ .D1 (dq_oe_n[0]),
+ .D2 (dq_oe_n[1]),
+ .R (1'b0),
+ .S (rst90)
+ );
+
+ //***************************************************************************
+ // Read data capture scheme description:
+ // Data capture consists of 3 ranks of flops, and a MUX
+ // 1. Rank 1 ("Stage 1"): IDDR captures delayed DDR DQ from memory using
+ // delayed DQS.
+ // - Data is split into 2 SDR streams, one each for rise and fall data.
+ // - BUFIO (DQS) input inverted to IDDR. IDDR configured in SAME_EDGE
+ // mode. This means that: (1) Q1 = fall data, Q2 = rise data,
+ // (2) Both rise and fall data are output on falling edge of DQS -
+ // rather than rise output being output on one edge of DQS, and fall
+ // data on the other edge if the IDDR were configured in OPPOSITE_EDGE
+ // mode. This simplifies Stage 2 capture (only one core clock edge
+ // used, removing effects of duty-cycle-distortion), and saves one
+ // fabric flop in Rank 3.
+ // 2. Rank 2 ("Stage 2"): Fabric flops are used to capture output of first
+ // rank into FPGA clock (CLK) domain. Each rising/falling SDR stream
+ // from IDDR is feed into two flops, one clocked off rising and one off
+ // falling edge of CLK. One of these flops is chosen, with the choice
+ // being the one that reduces # of DQ/DQS taps necessary to align Stage
+ // 1 and Stage 2. Same edge is used to capture both rise and fall SDR
+ // streams.
+ // 3. Rank 3 ("Stage 3"): Removes half-cycle paths in CLK domain from
+ // output of Rank 2. This stage, like Stage 2, is clocked by CLK. Note
+ // that Stage 3 can be expanded to also support SERDES functionality
+ // 4. Output MUX: Selects whether Stage 1 output is aligned to rising or
+ // falling edge of CLK (i.e. specifically this selects whether IDDR
+ // rise/fall output is transfered to rising or falling edge of CLK).
+ // Implementation:
+ // 1. Rank 1 is implemented using an IDDR primitive
+ // 2. Rank 2 is implemented using:
+ // - An RPM to fix the location of the capture flops near the DQ I/O.
+ // The exact RPM used depends on which I/O column (left, center,
+ // right) the DQ I/O is placed at - this affects the optimal location
+ // of the slice flops (or does it - can we always choose the two
+ // columns to slices to the immediate right of the I/O to use, no
+ // matter what the column?). The origin of the RPM must be set in the
+ // UCF file using the RLOC_ORIGIN constraint (where the original is
+ // based on the DQ I/O location).
+ // - Directed Routing Constraints ("DIRT strings") to fix the routing
+ // to the rank 2 fabric flops. This is done to minimize: (1) total
+ // route delay (and therefore minimize voltage/temperature-related
+ // variations), and (2) minimize skew both within each rising and
+ // falling data net, as well as between the rising and falling nets.
+ // The exact DIRT string used depends on: (1) which I/O column the
+ // DQ I/O is placed, and (2) whether the DQ I/O is placed on the
+ // "Master" or "Slave" I/O of a diff pair (DQ is not differential, but
+ // the routing will be affected by which of each I/O pair is used)
+ // 3. Rank 3 is implemented using fabric flops. No LOC or DIRT contraints
+ // are used, tools are expected to place these and meet PERIOD timing
+ // without constraints (constraints may be necessary for "full" designs,
+ // in this case, user may need to add LOC constraints - if this is the
+ // case, there are no constraints - other than meeting PERIOD timing -
+ // for rank 3 flops.
+ //***************************************************************************
+
+ //***************************************************************************
+ // MIG 2.2: Define AREA_GROUP = "DDR_CAPTURE_FFS" contain all RPM flops in
+ // design. In UCF file, add constraint:
+ // AREA_GROUP "DDR_CAPTURE_FFS" GROUP = CLOSED;
+ // This is done to prevent MAP from packing unrelated logic into
+ // the slices used by the RPMs. Doing so may cause the DIRT strings
+ // that define the IDDR -> fabric flop routing to later become
+ // unroutable during PAR because the unrelated logic placed by MAP
+ // may use routing resources required by the DIRT strings. MAP
+ // does not currently take into account DIRT strings when placing
+ // logic
+ //***************************************************************************
+
+ // IDELAY to delay incoming data for synchronization purposes
+ (* IODELAY_GROUP = IODELAY_GRP *) IODELAY #
+ (
+ .DELAY_SRC ("I"),
+ .IDELAY_TYPE ("VARIABLE"),
+ .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+ .IDELAY_VALUE (0),
+ .ODELAY_VALUE (0)
+ )
+ u_idelay_dq
+ (
+ .DATAOUT (dq_idelay),
+ .C (clkdiv0),
+ .CE (dlyce),
+ .DATAIN (),
+ .IDATAIN (dq_in),
+ .INC (dlyinc),
+ .ODATAIN (),
+ .RST (dlyrst),
+ .T ()
+ );
+
+ //***************************************************************************
+ // Rank 1 capture: Use IDDR to generate two SDR outputs
+ //***************************************************************************
+
+ // invert clock to IDDR in order to use SAME_EDGE mode (otherwise, we "run
+ // out of clocks" because DQS is not continuous
+ assign dq_iddr_clk = ~dqs;
+
+ //***************************************************************************
+ // Rank 2 capture: Use fabric flops to capture Rank 1 output. Use RPM and
+ // DIRT strings here.
+ // BEL ("Basic Element of Logic") and relative location constraints for
+ // second stage capture. C
+ // Varies according:
+ // (1) I/O column (left, center, right) used
+ // (2) Which I/O in I/O pair (master, slave) used
+ //***************************************************************************
+
+ // MODIFIED, RC, 06/13/08: Remove all references to DIRT, master/slave
+ // Take out generate statements - collapses to a single case
+
+ generate
+ if (FPGA_SPEED_GRADE == 3) begin: gen_stg2_sg3
+ IDDR #
+ (
+ .DDR_CLK_EDGE ("SAME_EDGE")
+ )
+ u_iddr_dq
+ (
+ .Q1 (stg1_out_fall_sg3),
+ .Q2 (stg1_out_rise_sg3),
+ .C (dq_iddr_clk),
+ .CE (ce),
+ .D (dq_idelay),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ //*********************************************************
+ // Slice #1 (posedge CLK): Used for:
+ // 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
+ // 2. stg2 falling edge -> stg3 rising edge transfer
+ //*********************************************************
+
+ // Stage 2 capture
+ FDRSE u_ff_stg2a_fall
+ (
+ .Q (stg2a_out_fall),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_fall_sg3),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ FDRSE u_ff_stg2a_rise
+ (
+ .Q (stg2a_out_rise),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_rise_sg3),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ // Stage 3 falling -> rising edge translation
+ FDRSE u_ff_stg3b_fall
+ (
+ .Q (stg3b_out_fall),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg2b_out_fall),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ FDRSE u_ff_stg3b_rise
+ (
+ .Q (stg3b_out_rise),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg2b_out_rise),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+
+ //*********************************************************
+ // Slice #2 (posedge CLK): Used for:
+ // 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
+ //*********************************************************
+
+ FDRSE_1 u_ff_stg2b_fall
+ (
+ .Q (stg2b_out_fall),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_fall_sg3),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+
+ FDRSE_1 u_ff_stg2b_rise
+ (
+ .Q (stg2b_out_rise),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_rise_sg3),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ end else if (FPGA_SPEED_GRADE == 2) begin: gen_stg2_sg2
+ IDDR #
+ (
+ .DDR_CLK_EDGE ("SAME_EDGE")
+ )
+ u_iddr_dq
+ (
+ .Q1 (stg1_out_fall_sg2),
+ .Q2 (stg1_out_rise_sg2),
+ .C (dq_iddr_clk),
+ .CE (ce),
+ .D (dq_idelay),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ //*********************************************************
+ // Slice #1 (posedge CLK): Used for:
+ // 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
+ // 2. stg2 falling edge -> stg3 rising edge transfer
+ //*********************************************************
+
+ // Stage 2 capture
+ FDRSE u_ff_stg2a_fall
+ (
+ .Q (stg2a_out_fall),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_fall_sg2),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ FDRSE u_ff_stg2a_rise
+ (
+ .Q (stg2a_out_rise),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_rise_sg2),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ // Stage 3 falling -> rising edge translation
+ FDRSE u_ff_stg3b_fall
+ (
+ .Q (stg3b_out_fall),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg2b_out_fall),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ FDRSE u_ff_stg3b_rise
+ (
+ .Q (stg3b_out_rise),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg2b_out_rise),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+
+ //*********************************************************
+ // Slice #2 (posedge CLK): Used for:
+ // 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
+ //*********************************************************
+
+ FDRSE_1 u_ff_stg2b_fall
+ (
+ .Q (stg2b_out_fall),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_fall_sg2),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+
+ FDRSE_1 u_ff_stg2b_rise
+ (
+ .Q (stg2b_out_rise),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_rise_sg2),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ end else if (FPGA_SPEED_GRADE == 1) begin: gen_stg2_sg1
+ IDDR #
+ (
+ .DDR_CLK_EDGE ("SAME_EDGE")
+ )
+ u_iddr_dq
+ (
+ .Q1 (stg1_out_fall_sg1),
+ .Q2 (stg1_out_rise_sg1),
+ .C (dq_iddr_clk),
+ .CE (ce),
+ .D (dq_idelay),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ //*********************************************************
+ // Slice #1 (posedge CLK): Used for:
+ // 1. IDDR transfer to CLK0 rising edge domain ("stg2a")
+ // 2. stg2 falling edge -> stg3 rising edge transfer
+ //*********************************************************
+
+ // Stage 2 capture
+ FDRSE u_ff_stg2a_fall
+ (
+ .Q (stg2a_out_fall),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_fall_sg1),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ FDRSE u_ff_stg2a_rise
+ (
+ .Q (stg2a_out_rise),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_rise_sg1),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ // Stage 3 falling -> rising edge translation
+ FDRSE u_ff_stg3b_fall
+ (
+ .Q (stg3b_out_fall),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg2b_out_fall),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ FDRSE u_ff_stg3b_rise
+ (
+ .Q (stg3b_out_rise),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg2b_out_rise),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+
+ //*********************************************************
+ // Slice #2 (posedge CLK): Used for:
+ // 1. IDDR transfer to CLK0 falling edge domain ("stg2b")
+ //*********************************************************
+
+ FDRSE_1 u_ff_stg2b_fall
+ (
+ .Q (stg2b_out_fall),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_fall_sg1),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+
+ FDRSE_1 u_ff_stg2b_rise
+ (
+ .Q (stg2b_out_rise),
+ .C (clk0),
+ .CE (1'b1),
+ .D (stg1_out_rise_sg1),
+ .R (1'b0),
+ .S (1'b0)
+ )/* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ end
+ endgenerate
+
+ //***************************************************************************
+ // Second stage flops clocked by posedge CLK0 don't need another layer of
+ // registering
+ //***************************************************************************
+
+ assign stg3a_out_rise = stg2a_out_rise;
+ assign stg3a_out_fall = stg2a_out_fall;
+
+ //*******************************************************************
+
+ assign rd_data_rise = (rd_data_sel) ? stg3a_out_rise : stg3b_out_rise;
+ assign rd_data_fall = (rd_data_sel) ? stg3a_out_fall : stg3b_out_fall;
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_chipscope.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_chipscope.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_chipscope.v (revision 3)
@@ -0,0 +1,114 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_chipscope.v
+// /___/ /\ Date Last Modified: $Data$
+// \ \ / \ Date Created: 9/14/06
+// \___\/\___\
+//
+//Device: Virtex-5
+//Purpose:
+// Skeleton Chipscope module declarations - for simulation only
+//Reference:
+//Revision History:
+//
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module icon4
+ (
+ control0,
+ control1,
+ control2,
+ control3
+ )
+ /* synthesis syn_black_box syn_noprune = 1 */;
+ output [35:0] control0;
+ output [35:0] control1;
+ output [35:0] control2;
+ output [35:0] control3;
+endmodule
+
+module vio_async_in192
+ (
+ control,
+ async_in
+ )
+ /* synthesis syn_black_box syn_noprune = 1 */;
+ input [35:0] control;
+ input [191:0] async_in;
+endmodule
+
+module vio_async_in96
+ (
+ control,
+ async_in
+ )
+ /* synthesis syn_black_box syn_noprune = 1 */;
+ input [35:0] control;
+ input [95:0] async_in;
+endmodule
+
+module vio_async_in100
+ (
+ control,
+ async_in
+ )
+ /* synthesis syn_black_box syn_noprune = 1 */;
+ input [35:0] control;
+ input [99:0] async_in;
+endmodule
+
+module vio_sync_out32
+ (
+ control,
+ clk,
+ sync_out
+ )
+ /* synthesis syn_black_box syn_noprune = 1 */;
+ input [35:0] control;
+ input clk;
+ output [31:0] sync_out;
+endmodule
\ No newline at end of file
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_mem_if_top.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_mem_if_top.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_mem_if_top.v (revision 3)
@@ -0,0 +1,380 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_mem_if_top.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR/DDR2
+//Purpose:
+// Top-level for parameterizable (DDR or DDR2) memory interface
+//Reference:
+//Revision History:
+// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
+// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
+// Rev 1.3 - Parameter CS_BITS added. PK. 10/8/08
+// Rev 1.4 - Parameter IODELAY_GRP added. PK. 11/27/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_mem_if_top #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter CKE_WIDTH = 1,
+ parameter CLK_WIDTH = 1,
+ parameter COL_WIDTH = 10,
+ parameter CS_BITS = 0,
+ parameter CS_NUM = 1,
+ parameter CS_WIDTH = 1,
+ parameter USE_DM_PORT = 1,
+ parameter DM_WIDTH = 9,
+ parameter DQ_WIDTH = 72,
+ parameter DQ_BITS = 7,
+ parameter DQ_PER_DQS = 8,
+ parameter DQS_BITS = 4,
+ parameter DQS_WIDTH = 9,
+ parameter HIGH_PERFORMANCE_MODE = "TRUE",
+ parameter IODELAY_GRP = "IODELAY_MIG",
+ parameter ODT_WIDTH = 1,
+ parameter ROW_WIDTH = 14,
+ parameter APPDATA_WIDTH = 144,
+ parameter ADDITIVE_LAT = 0,
+ parameter BURST_LEN = 4,
+ parameter BURST_TYPE = 0,
+ parameter CAS_LAT = 5,
+ parameter ECC_ENABLE = 0,
+ parameter MULTI_BANK_EN = 1,
+ parameter TWO_T_TIME_EN = 0,
+ parameter ODT_TYPE = 1,
+ parameter DDR_TYPE = 1,
+ parameter REDUCE_DRV = 0,
+ parameter REG_ENABLE = 1,
+ parameter TREFI_NS = 7800,
+ parameter TRAS = 40000,
+ parameter TRCD = 15000,
+ parameter TRFC = 105000,
+ parameter TRP = 15000,
+ parameter TRTP = 7500,
+ parameter TWR = 15000,
+ parameter TWTR = 10000,
+ parameter CLK_PERIOD = 3000,
+ parameter SIM_ONLY = 0,
+ parameter DEBUG_EN = 0,
+ parameter FPGA_SPEED_GRADE = 2
+ )
+ (
+ input clk0,
+ input clk90,
+ input clkdiv0,
+ input rst0,
+ input rst90,
+ input rstdiv0,
+ input [2:0] app_af_cmd,
+ input [30:0] app_af_addr,
+ input app_af_wren,
+ input app_wdf_wren,
+ input [APPDATA_WIDTH-1:0] app_wdf_data,
+ input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
+ output [1:0] rd_ecc_error,
+ output app_af_afull,
+ output app_wdf_afull,
+ output rd_data_valid,
+ output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
+ output phy_init_done,
+ output [CLK_WIDTH-1:0] ddr_ck,
+ output [CLK_WIDTH-1:0] ddr_ck_n,
+ output [ROW_WIDTH-1:0] ddr_addr,
+ output [BANK_WIDTH-1:0] ddr_ba,
+ output ddr_ras_n,
+ output ddr_cas_n,
+ output ddr_we_n,
+ output [CS_WIDTH-1:0] ddr_cs_n,
+ output [CKE_WIDTH-1:0] ddr_cke,
+ output [ODT_WIDTH-1:0] ddr_odt,
+ output [DM_WIDTH-1:0] ddr_dm,
+ inout [DQS_WIDTH-1:0] ddr_dqs,
+ inout [DQS_WIDTH-1:0] ddr_dqs_n,
+ inout [DQ_WIDTH-1:0] ddr_dq,
+ // Debug signals (optional use)
+ input dbg_idel_up_all,
+ input dbg_idel_down_all,
+ input dbg_idel_up_dq,
+ input dbg_idel_down_dq,
+ input dbg_idel_up_dqs,
+ input dbg_idel_down_dqs,
+ input dbg_idel_up_gate,
+ input dbg_idel_down_gate,
+ input [DQ_BITS-1:0] dbg_sel_idel_dq,
+ input dbg_sel_all_idel_dq,
+ input [DQS_BITS:0] dbg_sel_idel_dqs,
+ input dbg_sel_all_idel_dqs,
+ input [DQS_BITS:0] dbg_sel_idel_gate,
+ input dbg_sel_all_idel_gate,
+ output [3:0] dbg_calib_done,
+ output [3:0] dbg_calib_err,
+ output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
+ output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
+ );
+
+ wire [30:0] af_addr;
+ wire [2:0] af_cmd;
+ wire af_empty;
+ wire [ROW_WIDTH-1:0] ctrl_addr;
+ wire ctrl_af_rden;
+ wire [BANK_WIDTH-1:0] ctrl_ba;
+ wire ctrl_cas_n;
+ wire [CS_NUM-1:0] ctrl_cs_n;
+ wire ctrl_ras_n;
+ wire ctrl_rden;
+ wire ctrl_ref_flag;
+ wire ctrl_we_n;
+ wire ctrl_wren;
+ wire [DQS_WIDTH-1:0] phy_calib_rden;
+ wire [DQS_WIDTH-1:0] phy_calib_rden_sel;
+ wire [DQ_WIDTH-1:0] rd_data_fall;
+ wire [DQ_WIDTH-1:0] rd_data_rise;
+ wire [(2*DQ_WIDTH)-1:0] wdf_data;
+ wire [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data;
+ wire wdf_rden;
+
+ //***************************************************************************
+
+ ddr2_phy_top #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .CKE_WIDTH (CKE_WIDTH),
+ .CLK_WIDTH (CLK_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .CS_BITS (CS_BITS),
+ .CS_NUM (CS_NUM),
+ .CS_WIDTH (CS_WIDTH),
+ .USE_DM_PORT (USE_DM_PORT),
+ .DM_WIDTH (DM_WIDTH),
+ .DQ_WIDTH (DQ_WIDTH),
+ .DQ_BITS (DQ_BITS),
+ .DQ_PER_DQS (DQ_PER_DQS),
+ .DQS_BITS (DQS_BITS),
+ .DQS_WIDTH (DQS_WIDTH),
+ .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+ .IODELAY_GRP (IODELAY_GRP),
+ .ODT_WIDTH (ODT_WIDTH),
+ .ROW_WIDTH (ROW_WIDTH),
+ .TWO_T_TIME_EN (TWO_T_TIME_EN),
+ .ADDITIVE_LAT (ADDITIVE_LAT),
+ .BURST_LEN (BURST_LEN),
+ .BURST_TYPE (BURST_TYPE),
+ .CAS_LAT (CAS_LAT),
+ .ECC_ENABLE (ECC_ENABLE),
+ .ODT_TYPE (ODT_TYPE),
+ .DDR_TYPE (DDR_TYPE),
+ .REDUCE_DRV (REDUCE_DRV),
+ .REG_ENABLE (REG_ENABLE),
+ .TWR (TWR),
+ .CLK_PERIOD (CLK_PERIOD),
+ .SIM_ONLY (SIM_ONLY),
+ .DEBUG_EN (DEBUG_EN),
+ .FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
+ )
+ u_phy_top
+ (
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .clkdiv0 (clkdiv0),
+ .rst0 (rst0),
+ .rst90 (rst90),
+ .rstdiv0 (rstdiv0),
+ .ctrl_wren (ctrl_wren),
+ .ctrl_addr (ctrl_addr),
+ .ctrl_ba (ctrl_ba),
+ .ctrl_ras_n (ctrl_ras_n),
+ .ctrl_cas_n (ctrl_cas_n),
+ .ctrl_we_n (ctrl_we_n),
+ .ctrl_cs_n (ctrl_cs_n),
+ .ctrl_rden (ctrl_rden),
+ .ctrl_ref_flag (ctrl_ref_flag),
+ .wdf_data (wdf_data),
+ .wdf_mask_data (wdf_mask_data),
+ .wdf_rden (wdf_rden),
+ .phy_init_done (phy_init_done),
+ .phy_calib_rden (phy_calib_rden),
+ .phy_calib_rden_sel (phy_calib_rden_sel),
+ .rd_data_rise (rd_data_rise),
+ .rd_data_fall (rd_data_fall),
+ .ddr_ck (ddr_ck),
+ .ddr_ck_n (ddr_ck_n),
+ .ddr_addr (ddr_addr),
+ .ddr_ba (ddr_ba),
+ .ddr_ras_n (ddr_ras_n),
+ .ddr_cas_n (ddr_cas_n),
+ .ddr_we_n (ddr_we_n),
+ .ddr_cs_n (ddr_cs_n),
+ .ddr_cke (ddr_cke),
+ .ddr_odt (ddr_odt),
+ .ddr_dm (ddr_dm),
+ .ddr_dqs (ddr_dqs),
+ .ddr_dqs_n (ddr_dqs_n),
+ .ddr_dq (ddr_dq),
+ .dbg_idel_up_all (dbg_idel_up_all),
+ .dbg_idel_down_all (dbg_idel_down_all),
+ .dbg_idel_up_dq (dbg_idel_up_dq),
+ .dbg_idel_down_dq (dbg_idel_down_dq),
+ .dbg_idel_up_dqs (dbg_idel_up_dqs),
+ .dbg_idel_down_dqs (dbg_idel_down_dqs),
+ .dbg_idel_up_gate (dbg_idel_up_gate),
+ .dbg_idel_down_gate (dbg_idel_down_gate),
+ .dbg_sel_idel_dq (dbg_sel_idel_dq),
+ .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
+ .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
+ .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
+ .dbg_sel_idel_gate (dbg_sel_idel_gate),
+ .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
+ .dbg_calib_done (dbg_calib_done),
+ .dbg_calib_err (dbg_calib_err),
+ .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
+ .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
+ .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
+ .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
+ .dbg_calib_rden_dly (dbg_calib_rden_dly),
+ .dbg_calib_gate_dly (dbg_calib_gate_dly)
+ );
+
+ ddr2_usr_top #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .CS_BITS (CS_BITS),
+ .DQ_WIDTH (DQ_WIDTH),
+ .DQ_PER_DQS (DQ_PER_DQS),
+ .DQS_WIDTH (DQS_WIDTH),
+ .APPDATA_WIDTH (APPDATA_WIDTH),
+ .ECC_ENABLE (ECC_ENABLE),
+ .ROW_WIDTH (ROW_WIDTH)
+ )
+ u_usr_top
+ (
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .rst0 (rst0),
+ .rd_data_in_rise (rd_data_rise),
+ .rd_data_in_fall (rd_data_fall),
+ .phy_calib_rden (phy_calib_rden),
+ .phy_calib_rden_sel(phy_calib_rden_sel),
+ .rd_data_valid (rd_data_valid),
+ .rd_ecc_error (rd_ecc_error),
+ .rd_data_fifo_out (rd_data_fifo_out),
+ .app_af_cmd (app_af_cmd),
+ .app_af_addr (app_af_addr),
+ .app_af_wren (app_af_wren),
+ .ctrl_af_rden (ctrl_af_rden),
+ .af_cmd (af_cmd),
+ .af_addr (af_addr),
+ .af_empty (af_empty),
+ .app_af_afull (app_af_afull),
+ .app_wdf_wren (app_wdf_wren),
+ .app_wdf_data (app_wdf_data),
+ .app_wdf_mask_data (app_wdf_mask_data),
+ .wdf_rden (wdf_rden),
+ .app_wdf_afull (app_wdf_afull),
+ .wdf_data (wdf_data),
+ .wdf_mask_data (wdf_mask_data)
+ );
+
+
+ ddr2_ctrl #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .CS_BITS (CS_BITS),
+ .CS_NUM (CS_NUM),
+ .ROW_WIDTH (ROW_WIDTH),
+ .ADDITIVE_LAT (ADDITIVE_LAT),
+ .BURST_LEN (BURST_LEN),
+ .CAS_LAT (CAS_LAT),
+ .ECC_ENABLE (ECC_ENABLE),
+ .REG_ENABLE (REG_ENABLE),
+ .MULTI_BANK_EN (MULTI_BANK_EN),
+ .TWO_T_TIME_EN (TWO_T_TIME_EN),
+ .TREFI_NS (TREFI_NS),
+ .TRAS (TRAS),
+ .TRCD (TRCD),
+ .TRFC (TRFC),
+ .TRP (TRP),
+ .TRTP (TRTP),
+ .TWR (TWR),
+ .TWTR (TWTR),
+ .CLK_PERIOD (CLK_PERIOD),
+ .DDR_TYPE (DDR_TYPE)
+ )
+ u_ctrl
+ (
+ .clk (clk0),
+ .rst (rst0),
+ .af_cmd (af_cmd),
+ .af_addr (af_addr),
+ .af_empty (af_empty),
+ .phy_init_done (phy_init_done),
+ .ctrl_ref_flag (ctrl_ref_flag),
+ .ctrl_af_rden (ctrl_af_rden),
+ .ctrl_wren (ctrl_wren),
+ .ctrl_rden (ctrl_rden),
+ .ctrl_addr (ctrl_addr),
+ .ctrl_ba (ctrl_ba),
+ .ctrl_ras_n (ctrl_ras_n),
+ .ctrl_cas_n (ctrl_cas_n),
+ .ctrl_we_n (ctrl_we_n),
+ .ctrl_cs_n (ctrl_cs_n)
+ );
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_infrastructure.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_infrastructure.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_infrastructure.v (revision 3)
@@ -0,0 +1,150 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_infrastructure.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// Clock distribution and reset synchronization
+//Reference:
+//Revision History:
+// Rev 1.1 - Port name changed from dcm_lock to locked. PK. 10/14/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_infrastructure #
+ (
+ parameter RST_ACT_LOW = 1
+ )
+ (
+ input clk0,
+ input clk90,
+ input clk200,
+ input clkdiv0,
+ input locked,
+ input sys_rst_n,
+ input idelay_ctrl_rdy,
+ output rst0,
+ output rst90,
+ output rst200,
+ output rstdiv0
+ );
+
+ // # of clock cycles to delay deassertion of reset. Needs to be a fairly
+ // high number not so much for metastability protection, but to give time
+ // for reset (i.e. stable clock cycles) to propagate through all state
+ // machines and to all control signals (i.e. not all control signals have
+ // resets, instead they rely on base state logic being reset, and the effect
+ // of that reset propagating through the logic). Need this because we may not
+ // be getting stable clock cycles while reset asserted (i.e. since reset
+ // depends on DCM lock status)
+ localparam RST_SYNC_NUM = 25;
+
+ reg [RST_SYNC_NUM-1:0] rst0_sync_r /* synthesis syn_maxfan = 10 */;
+ reg [RST_SYNC_NUM-1:0] rst200_sync_r /* synthesis syn_maxfan = 10 */;
+ reg [RST_SYNC_NUM-1:0] rst90_sync_r /* synthesis syn_maxfan = 10 */;
+ reg [(RST_SYNC_NUM/2)-1:0] rstdiv0_sync_r /* synthesis syn_maxfan = 10 */;
+ wire rst_tmp;
+ wire sys_clk_ibufg;
+ wire sys_rst;
+
+ assign sys_rst = RST_ACT_LOW ? ~sys_rst_n: sys_rst_n;
+
+ //***************************************************************************
+ // Reset synchronization
+ // NOTES:
+ // 1. shut down the whole operation if the DCM hasn't yet locked (and by
+ // inference, this means that external SYS_RST_IN has been asserted -
+ // DCM deasserts LOCKED as soon as SYS_RST_IN asserted)
+ // 2. In the case of all resets except rst200, also assert reset if the
+ // IDELAY master controller is not yet ready
+ // 3. asynchronously assert reset. This was we can assert reset even if
+ // there is no clock (needed for things like 3-stating output buffers).
+ // reset deassertion is synchronous.
+ //***************************************************************************
+
+ assign rst_tmp = sys_rst | ~locked | ~idelay_ctrl_rdy;
+
+ // synthesis attribute max_fanout of rst0_sync_r is 10
+ always @(posedge clk0 or posedge rst_tmp)
+ if (rst_tmp)
+ rst0_sync_r <= {RST_SYNC_NUM{1'b1}};
+ else
+ // logical left shift by one (pads with 0)
+ rst0_sync_r <= rst0_sync_r << 1;
+
+ // synthesis attribute max_fanout of rstdiv0_sync_r is 10
+ always @(posedge clkdiv0 or posedge rst_tmp)
+ if (rst_tmp)
+ rstdiv0_sync_r <= {(RST_SYNC_NUM/2){1'b1}};
+ else
+ // logical left shift by one (pads with 0)
+ rstdiv0_sync_r <= rstdiv0_sync_r << 1;
+
+ // synthesis attribute max_fanout of rst90_sync_r is 10
+ always @(posedge clk90 or posedge rst_tmp)
+ if (rst_tmp)
+ rst90_sync_r <= {RST_SYNC_NUM{1'b1}};
+ else
+ rst90_sync_r <= rst90_sync_r << 1;
+
+ // make sure CLK200 doesn't depend on IDELAY_CTRL_RDY, else chicken n' egg
+ // synthesis attribute max_fanout of rst200_sync_r is 10
+ always @(posedge clk200 or negedge locked)
+ if (!locked)
+ rst200_sync_r <= {RST_SYNC_NUM{1'b1}};
+ else
+ rst200_sync_r <= rst200_sync_r << 1;
+
+ assign rst0 = rst0_sync_r[RST_SYNC_NUM-1];
+ assign rst90 = rst90_sync_r[RST_SYNC_NUM-1];
+ assign rst200 = rst200_sync_r[RST_SYNC_NUM-1];
+ assign rstdiv0 = rstdiv0_sync_r[(RST_SYNC_NUM/2)-1];
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_wr.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_wr.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_wr.v (revision 3)
@@ -0,0 +1,334 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_usr_wr.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Mon Aug 28 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR/DDR2
+//Purpose:
+// This module instantiates the modules containing internal FIFOs
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_usr_wr #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter COL_WIDTH = 10,
+ parameter CS_BITS = 0,
+ parameter DQ_WIDTH = 72,
+ parameter APPDATA_WIDTH = 144,
+ parameter ECC_ENABLE = 0,
+ parameter ROW_WIDTH = 14
+ )
+ (
+ input clk0,
+ input clk90,
+ input rst0,
+ // Write data FIFO interface
+ input app_wdf_wren,
+ input [APPDATA_WIDTH-1:0] app_wdf_data,
+ input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
+ input wdf_rden,
+ output app_wdf_afull,
+ output [(2*DQ_WIDTH)-1:0] wdf_data,
+ output [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data
+ );
+
+ // determine number of FIFO72's to use based on data width
+ // round up to next integer value when determining WDF_FIFO_NUM
+ localparam WDF_FIFO_NUM = (ECC_ENABLE) ? (APPDATA_WIDTH+63)/64 :
+ ((2*DQ_WIDTH)+63)/64;
+ // MASK_WIDTH = number of bytes in data bus
+ localparam MASK_WIDTH = DQ_WIDTH/8;
+
+ wire [WDF_FIFO_NUM-1:0] i_wdf_afull;
+ wire [DQ_WIDTH-1:0] i_wdf_data_fall_in;
+ wire [DQ_WIDTH-1:0] i_wdf_data_fall_out;
+ wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_in;
+ wire [(64*WDF_FIFO_NUM)-1:0] i_wdf_data_out;
+ wire [DQ_WIDTH-1:0] i_wdf_data_rise_in;
+ wire [DQ_WIDTH-1:0] i_wdf_data_rise_out;
+ wire [MASK_WIDTH-1:0] i_wdf_mask_data_fall_in;
+ wire [MASK_WIDTH-1:0] i_wdf_mask_data_fall_out;
+ wire [(8*WDF_FIFO_NUM)-1:0] i_wdf_mask_data_in;
+ wire [(8*WDF_FIFO_NUM)-1:0] i_wdf_mask_data_out;
+ wire [MASK_WIDTH-1:0] i_wdf_mask_data_rise_in;
+ wire [MASK_WIDTH-1:0] i_wdf_mask_data_rise_out;
+ reg rst_r;
+
+ // ECC signals
+ wire [(2*DQ_WIDTH)-1:0] i_wdf_data_out_ecc;
+ wire [((2*DQ_WIDTH)/8)-1:0] i_wdf_mask_data_out_ecc;
+ wire [63:0] i_wdf_mask_data_out_ecc_wire;
+ wire [((2*DQ_WIDTH)/8)-1:0] mask_data_in_ecc;
+ wire [63:0] mask_data_in_ecc_wire;
+
+ //***************************************************************************
+
+ assign app_wdf_afull = i_wdf_afull[0];
+
+ always @(posedge clk0 )
+ rst_r <= rst0;
+
+ genvar wdf_di_i;
+ genvar wdf_do_i;
+ genvar mask_i;
+ genvar wdf_i;
+ generate
+ if(ECC_ENABLE) begin // ECC code
+
+ assign wdf_data = i_wdf_data_out_ecc;
+
+ // the byte 9 dm is always held to 0
+ assign wdf_mask_data = i_wdf_mask_data_out_ecc;
+
+
+
+ // generate for write data fifo .
+ for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
+
+ FIFO36_72 #
+ (
+ .ALMOST_EMPTY_OFFSET (9'h007),
+ .ALMOST_FULL_OFFSET (9'h00F),
+ .DO_REG (1), // extra CC output delay
+ .EN_ECC_WRITE ("TRUE"),
+ .EN_ECC_READ ("FALSE"),
+ .EN_SYN ("FALSE"),
+ .FIRST_WORD_FALL_THROUGH ("FALSE")
+ )
+ u_wdf_ecc
+ (
+ .ALMOSTEMPTY (),
+ .ALMOSTFULL (i_wdf_afull[wdf_i]),
+ .DBITERR (),
+ .DO (i_wdf_data_out_ecc[((64*(wdf_i+1))+(wdf_i *8))-1:
+ (64*wdf_i)+(wdf_i *8)]),
+ .DOP (i_wdf_data_out_ecc[(72*(wdf_i+1))-1:
+ (64*(wdf_i+1))+ (8*wdf_i) ]),
+ .ECCPARITY (),
+ .EMPTY (),
+ .FULL (),
+ .RDCOUNT (),
+ .RDERR (),
+ .SBITERR (),
+ .WRCOUNT (),
+ .WRERR (),
+ .DI (app_wdf_data[(64*(wdf_i+1))-1:
+ (64*wdf_i)]),
+ .DIP (),
+ .RDCLK (clk90),
+ .RDEN (wdf_rden),
+ .RST (rst_r), // or can use rst0
+ .WRCLK (clk0),
+ .WREN (app_wdf_wren)
+ );
+ end
+
+ // remapping the mask data. The mask data from user i/f does not have
+ // the mask for the ECC byte. Assigning 0 to the ECC mask byte.
+ for (mask_i = 0; mask_i < (DQ_WIDTH)/36;
+ mask_i = mask_i +1) begin: gen_mask
+ assign mask_data_in_ecc[((8*(mask_i+1))+ mask_i)-1:((8*mask_i)+mask_i)]
+ = app_wdf_mask_data[(8*(mask_i+1))-1:8*(mask_i)] ;
+ assign mask_data_in_ecc[((8*(mask_i+1))+mask_i)] = 1'd0;
+ end
+
+ // assign ecc bits to temp variables to avoid
+ // sim warnings. Not all the 64 bits of the fifo
+ // are used in ECC mode.
+ assign mask_data_in_ecc_wire[((2*DQ_WIDTH)/8)-1:0] = mask_data_in_ecc;
+ assign mask_data_in_ecc_wire[63:((2*DQ_WIDTH)/8)] =
+ {(64-((2*DQ_WIDTH)/8)){1'b0}};
+ assign i_wdf_mask_data_out_ecc =
+ i_wdf_mask_data_out_ecc_wire[((2*DQ_WIDTH)/8)-1:0];
+
+
+ FIFO36_72 #
+ (
+ .ALMOST_EMPTY_OFFSET (9'h007),
+ .ALMOST_FULL_OFFSET (9'h00F),
+ .DO_REG (1), // extra CC output delay
+ .EN_ECC_WRITE ("TRUE"),
+ .EN_ECC_READ ("FALSE"),
+ .EN_SYN ("FALSE"),
+ .FIRST_WORD_FALL_THROUGH ("FALSE")
+ )
+ u_wdf_ecc_mask
+ (
+ .ALMOSTEMPTY (),
+ .ALMOSTFULL (),
+ .DBITERR (),
+ .DO (i_wdf_mask_data_out_ecc_wire),
+ .DOP (),
+ .ECCPARITY (),
+ .EMPTY (),
+ .FULL (),
+ .RDCOUNT (),
+ .RDERR (),
+ .SBITERR (),
+ .WRCOUNT (),
+ .WRERR (),
+ .DI (mask_data_in_ecc_wire),
+ .DIP (),
+ .RDCLK (clk90),
+ .RDEN (wdf_rden),
+ .RST (rst_r), // or can use rst0
+ .WRCLK (clk0),
+ .WREN (app_wdf_wren)
+ );
+ end else begin
+
+ //***********************************************************************
+
+ // Define intermediate buses:
+ assign i_wdf_data_rise_in
+ = app_wdf_data[DQ_WIDTH-1:0];
+ assign i_wdf_data_fall_in
+ = app_wdf_data[(2*DQ_WIDTH)-1:DQ_WIDTH];
+ assign i_wdf_mask_data_rise_in
+ = app_wdf_mask_data[MASK_WIDTH-1:0];
+ assign i_wdf_mask_data_fall_in
+ = app_wdf_mask_data[(2*MASK_WIDTH)-1:MASK_WIDTH];
+
+ //***********************************************************************
+ // Write data FIFO Input:
+ // Arrange DQ's so that the rise data and fall data are interleaved.
+ // the data arrives at the input of the wdf fifo as {fall,rise}.
+ // It is remapped as:
+ // {...fall[15:8],rise[15:8],fall[7:0],rise[7:0]}
+ // This is done to avoid having separate fifo's for rise and fall data
+ // and to keep rise/fall data for the same DQ's on same FIFO
+ // Data masks are interleaved in a similar manner
+ // NOTE: Initialization data from PHY_INIT module does not need to be
+ // interleaved - it's already in the correct format - and the same
+ // initialization pattern from PHY_INIT is sent to all write FIFOs
+ //***********************************************************************
+
+ for (wdf_di_i = 0; wdf_di_i < MASK_WIDTH;
+ wdf_di_i = wdf_di_i + 1) begin: gen_wdf_data_in
+ assign i_wdf_data_in[(16*wdf_di_i)+15:(16*wdf_di_i)]
+ = {i_wdf_data_fall_in[(8*wdf_di_i)+7:(8*wdf_di_i)],
+ i_wdf_data_rise_in[(8*wdf_di_i)+7:(8*wdf_di_i)]};
+ assign i_wdf_mask_data_in[(2*wdf_di_i)+1:(2*wdf_di_i)]
+ = {i_wdf_mask_data_fall_in[wdf_di_i],
+ i_wdf_mask_data_rise_in[wdf_di_i]};
+ end
+
+ //***********************************************************************
+ // Write data FIFO Output:
+ // FIFO DQ and mask outputs must be untangled and put in the standard
+ // format of {fall,rise}. Same goes for mask output
+ //***********************************************************************
+
+ for (wdf_do_i = 0; wdf_do_i < MASK_WIDTH;
+ wdf_do_i = wdf_do_i + 1) begin: gen_wdf_data_out
+ assign i_wdf_data_rise_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
+ = i_wdf_data_out[(16*wdf_do_i)+7:(16*wdf_do_i)];
+ assign i_wdf_data_fall_out[(8*wdf_do_i)+7:(8*wdf_do_i)]
+ = i_wdf_data_out[(16*wdf_do_i)+15:(16*wdf_do_i)+8];
+ assign i_wdf_mask_data_rise_out[wdf_do_i]
+ = i_wdf_mask_data_out[2*wdf_do_i];
+ assign i_wdf_mask_data_fall_out[wdf_do_i]
+ = i_wdf_mask_data_out[(2*wdf_do_i)+1];
+ end
+
+ assign wdf_data = {i_wdf_data_fall_out,
+ i_wdf_data_rise_out};
+
+ assign wdf_mask_data = {i_wdf_mask_data_fall_out,
+ i_wdf_mask_data_rise_out};
+
+ //***********************************************************************
+
+ for (wdf_i = 0; wdf_i < WDF_FIFO_NUM; wdf_i = wdf_i + 1) begin: gen_wdf
+
+ FIFO36_72 #
+ (
+ .ALMOST_EMPTY_OFFSET (9'h007),
+ .ALMOST_FULL_OFFSET (9'h00F),
+ .DO_REG (1), // extra CC output delay
+ .EN_ECC_WRITE ("FALSE"),
+ .EN_ECC_READ ("FALSE"),
+ .EN_SYN ("FALSE"),
+ .FIRST_WORD_FALL_THROUGH ("FALSE")
+ )
+ u_wdf
+ (
+ .ALMOSTEMPTY (),
+ .ALMOSTFULL (i_wdf_afull[wdf_i]),
+ .DBITERR (),
+ .DO (i_wdf_data_out[(64*(wdf_i+1))-1:64*wdf_i]),
+ .DOP (i_wdf_mask_data_out[(8*(wdf_i+1))-1:8*wdf_i]),
+ .ECCPARITY (),
+ .EMPTY (),
+ .FULL (),
+ .RDCOUNT (),
+ .RDERR (),
+ .SBITERR (),
+ .WRCOUNT (),
+ .WRERR (),
+ .DI (i_wdf_data_in[(64*(wdf_i+1))-1:64*wdf_i]),
+ .DIP (i_wdf_mask_data_in[(8*(wdf_i+1))-1:8*wdf_i]),
+ .RDCLK (clk90),
+ .RDEN (wdf_rden),
+ .RST (rst_r), // or can use rst0
+ .WRCLK (clk0),
+ .WREN (app_wdf_wren)
+ );
+ end
+ end
+ endgenerate
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_top.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_top.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_top.v (revision 3)
@@ -0,0 +1,395 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_phy_top.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// Top-level for memory physical layer (PHY) interface
+//Reference:
+//Revision History:
+// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
+// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
+// Rev 1.3 - Parameter CS_BITS added. PK. 10/8/08
+// Rev 1.4 - Parameter IODELAY_GRP added. PK. 11/27/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+(* X_CORE_INFO = "mig_v3_61_ddr2_sdram_v5, Coregen 12.4" , CORE_GENERATION_INFO = "ddr2_sdram_v5,mig_v3_61,{component_name=ddr2_phy_top, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=3, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, CLK_PERIOD=8000, RST_ACT_LOW=1, INTERFACE_TYPE=DDR2_SDRAM, LANGUAGE=Verilog, SYNTHESIS_TOOL=ISE, NO_OF_CONTROLLERS=1}" *)
+module ddr2_phy_top #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter CLK_WIDTH = 1,
+ parameter CKE_WIDTH = 1,
+ parameter COL_WIDTH = 10,
+ parameter CS_BITS = 0,
+ parameter CS_NUM = 1,
+ parameter CS_WIDTH = 1,
+ parameter USE_DM_PORT = 1,
+ parameter DM_WIDTH = 9,
+ parameter DQ_WIDTH = 72,
+ parameter DQ_BITS = 7,
+ parameter DQ_PER_DQS = 8,
+ parameter DQS_WIDTH = 9,
+ parameter DQS_BITS = 4,
+ parameter HIGH_PERFORMANCE_MODE = "TRUE",
+ parameter IODELAY_GRP = "IODELAY_MIG",
+ parameter ODT_WIDTH = 1,
+ parameter ROW_WIDTH = 14,
+ parameter ADDITIVE_LAT = 0,
+ parameter TWO_T_TIME_EN = 0,
+ parameter BURST_LEN = 4,
+ parameter BURST_TYPE = 0,
+ parameter CAS_LAT = 5,
+ parameter TWR = 15000,
+ parameter ECC_ENABLE = 0,
+ parameter ODT_TYPE = 1,
+ parameter DDR_TYPE = 1,
+ parameter REDUCE_DRV = 0,
+ parameter REG_ENABLE = 1,
+ parameter CLK_PERIOD = 3000,
+ parameter SIM_ONLY = 0,
+ parameter DEBUG_EN = 0,
+ parameter FPGA_SPEED_GRADE = 2
+ )
+ (
+ input clk0,
+ input clk90,
+ input clkdiv0,
+ input rst0,
+ input rst90,
+ input rstdiv0,
+ input ctrl_wren,
+ input [ROW_WIDTH-1:0] ctrl_addr,
+ input [BANK_WIDTH-1:0] ctrl_ba,
+ input ctrl_ras_n,
+ input ctrl_cas_n,
+ input ctrl_we_n,
+ input [CS_NUM-1:0] ctrl_cs_n,
+ input ctrl_rden,
+ input ctrl_ref_flag,
+ input [(2*DQ_WIDTH)-1:0] wdf_data,
+ input [(2*DQ_WIDTH/8)-1:0] wdf_mask_data,
+ output wdf_rden,
+ output phy_init_done,
+ output [DQS_WIDTH-1:0] phy_calib_rden,
+ output [DQS_WIDTH-1:0] phy_calib_rden_sel,
+ output [DQ_WIDTH-1:0] rd_data_rise,
+ output [DQ_WIDTH-1:0] rd_data_fall,
+ output [CLK_WIDTH-1:0] ddr_ck,
+ output [CLK_WIDTH-1:0] ddr_ck_n,
+ output [ROW_WIDTH-1:0] ddr_addr,
+ output [BANK_WIDTH-1:0] ddr_ba,
+ output ddr_ras_n,
+ output ddr_cas_n,
+ output ddr_we_n,
+ output [CS_WIDTH-1:0] ddr_cs_n,
+ output [CKE_WIDTH-1:0] ddr_cke,
+ output [ODT_WIDTH-1:0] ddr_odt,
+ output [DM_WIDTH-1:0] ddr_dm,
+ inout [DQS_WIDTH-1:0] ddr_dqs,
+ inout [DQS_WIDTH-1:0] ddr_dqs_n,
+ inout [DQ_WIDTH-1:0] ddr_dq,
+ // Debug signals (optional use)
+ input dbg_idel_up_all,
+ input dbg_idel_down_all,
+ input dbg_idel_up_dq,
+ input dbg_idel_down_dq,
+ input dbg_idel_up_dqs,
+ input dbg_idel_down_dqs,
+ input dbg_idel_up_gate,
+ input dbg_idel_down_gate,
+ input [DQ_BITS-1:0] dbg_sel_idel_dq,
+ input dbg_sel_all_idel_dq,
+ input [DQS_BITS:0] dbg_sel_idel_dqs,
+ input dbg_sel_all_idel_dqs,
+ input [DQS_BITS:0] dbg_sel_idel_gate,
+ input dbg_sel_all_idel_gate,
+ output [3:0] dbg_calib_done,
+ output [3:0] dbg_calib_err,
+ output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
+ output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
+ );
+
+ wire [3:0] calib_done;
+ wire calib_ref_done;
+ wire calib_ref_req;
+ wire [3:0] calib_start;
+ wire dm_ce;
+ wire [1:0] dq_oe_n;
+ wire dqs_oe_n;
+ wire dqs_rst_n;
+ wire [(DQ_WIDTH/8)-1:0] mask_data_fall;
+ wire [(DQ_WIDTH/8)-1:0] mask_data_rise;
+ wire [CS_NUM-1:0] odt;
+ wire [ROW_WIDTH-1:0] phy_init_addr;
+ wire [BANK_WIDTH-1:0] phy_init_ba;
+ wire phy_init_cas_n;
+ wire [CKE_WIDTH-1:0] phy_init_cke;
+ wire [CS_NUM-1:0] phy_init_cs_n;
+ wire phy_init_data_sel;
+ wire phy_init_ras_n;
+ wire phy_init_rden;
+ wire phy_init_we_n;
+ wire phy_init_wren;
+ wire [DQ_WIDTH-1:0] wr_data_fall;
+ wire [DQ_WIDTH-1:0] wr_data_rise;
+
+ //***************************************************************************
+
+ ddr2_phy_write #
+ (
+ .DQ_WIDTH (DQ_WIDTH),
+ .CS_NUM (CS_NUM),
+ .ADDITIVE_LAT (ADDITIVE_LAT),
+ .CAS_LAT (CAS_LAT),
+ .ECC_ENABLE (ECC_ENABLE),
+ .ODT_TYPE (ODT_TYPE),
+ .REG_ENABLE (REG_ENABLE),
+ .DDR_TYPE (DDR_TYPE)
+ )
+ u_phy_write
+ (
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .rst90 (rst90),
+ .wdf_data (wdf_data),
+ .wdf_mask_data (wdf_mask_data),
+ .ctrl_wren (ctrl_wren),
+ .phy_init_wren (phy_init_wren),
+ .phy_init_data_sel (phy_init_data_sel),
+ .dm_ce (dm_ce),
+ .dq_oe_n (dq_oe_n),
+ .dqs_oe_n (dqs_oe_n),
+ .dqs_rst_n (dqs_rst_n),
+ .wdf_rden (wdf_rden),
+ .odt (odt),
+ .wr_data_rise (wr_data_rise),
+ .wr_data_fall (wr_data_fall),
+ .mask_data_rise (mask_data_rise),
+ .mask_data_fall (mask_data_fall)
+ );
+
+ ddr2_phy_io #
+ (
+ .CLK_WIDTH (CLK_WIDTH),
+ .USE_DM_PORT (USE_DM_PORT),
+ .DM_WIDTH (DM_WIDTH),
+ .DQ_WIDTH (DQ_WIDTH),
+ .DQ_BITS (DQ_BITS),
+ .DQ_PER_DQS (DQ_PER_DQS),
+ .DQS_BITS (DQS_BITS),
+ .DQS_WIDTH (DQS_WIDTH),
+ .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+ .IODELAY_GRP (IODELAY_GRP),
+ .ODT_WIDTH (ODT_WIDTH),
+ .ADDITIVE_LAT (ADDITIVE_LAT),
+ .CAS_LAT (CAS_LAT),
+ .REG_ENABLE (REG_ENABLE),
+ .CLK_PERIOD (CLK_PERIOD),
+ .DDR_TYPE (DDR_TYPE),
+ .SIM_ONLY (SIM_ONLY),
+ .DEBUG_EN (DEBUG_EN),
+ .FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
+ )
+ u_phy_io
+ (
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .clkdiv0 (clkdiv0),
+ .rst0 (rst0),
+ .rst90 (rst90),
+ .rstdiv0 (rstdiv0),
+ .dm_ce (dm_ce),
+ .dq_oe_n (dq_oe_n),
+ .dqs_oe_n (dqs_oe_n),
+ .dqs_rst_n (dqs_rst_n),
+ .calib_start (calib_start),
+ .ctrl_rden (ctrl_rden),
+ .phy_init_rden (phy_init_rden),
+ .calib_ref_done (calib_ref_done),
+ .calib_done (calib_done),
+ .calib_ref_req (calib_ref_req),
+ .calib_rden (phy_calib_rden),
+ .calib_rden_sel (phy_calib_rden_sel),
+ .wr_data_rise (wr_data_rise),
+ .wr_data_fall (wr_data_fall),
+ .mask_data_rise (mask_data_rise),
+ .mask_data_fall (mask_data_fall),
+ .rd_data_rise (rd_data_rise),
+ .rd_data_fall (rd_data_fall),
+ .ddr_ck (ddr_ck),
+ .ddr_ck_n (ddr_ck_n),
+ .ddr_dm (ddr_dm),
+ .ddr_dqs (ddr_dqs),
+ .ddr_dqs_n (ddr_dqs_n),
+ .ddr_dq (ddr_dq),
+ .dbg_idel_up_all (dbg_idel_up_all),
+ .dbg_idel_down_all (dbg_idel_down_all),
+ .dbg_idel_up_dq (dbg_idel_up_dq),
+ .dbg_idel_down_dq (dbg_idel_down_dq),
+ .dbg_idel_up_dqs (dbg_idel_up_dqs),
+ .dbg_idel_down_dqs (dbg_idel_down_dqs),
+ .dbg_idel_up_gate (dbg_idel_up_gate),
+ .dbg_idel_down_gate (dbg_idel_down_gate),
+ .dbg_sel_idel_dq (dbg_sel_idel_dq),
+ .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
+ .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
+ .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
+ .dbg_sel_idel_gate (dbg_sel_idel_gate),
+ .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
+ .dbg_calib_done (dbg_calib_done),
+ .dbg_calib_err (dbg_calib_err),
+ .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
+ .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
+ .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
+ .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
+ .dbg_calib_rden_dly (dbg_calib_rden_dly),
+ .dbg_calib_gate_dly (dbg_calib_gate_dly)
+ );
+
+ ddr2_phy_ctl_io #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .CKE_WIDTH (CKE_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .CS_NUM (CS_NUM),
+ .CS_WIDTH (CS_WIDTH),
+ .TWO_T_TIME_EN (TWO_T_TIME_EN),
+ .ODT_WIDTH (ODT_WIDTH),
+ .ROW_WIDTH (ROW_WIDTH),
+ .DDR_TYPE (DDR_TYPE)
+ )
+ u_phy_ctl_io
+ (
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .rst0 (rst0),
+ .rst90 (rst90),
+ .ctrl_addr (ctrl_addr),
+ .ctrl_ba (ctrl_ba),
+ .ctrl_ras_n (ctrl_ras_n),
+ .ctrl_cas_n (ctrl_cas_n),
+ .ctrl_we_n (ctrl_we_n),
+ .ctrl_cs_n (ctrl_cs_n),
+ .phy_init_addr (phy_init_addr),
+ .phy_init_ba (phy_init_ba),
+ .phy_init_ras_n (phy_init_ras_n),
+ .phy_init_cas_n (phy_init_cas_n),
+ .phy_init_we_n (phy_init_we_n),
+ .phy_init_cs_n (phy_init_cs_n),
+ .phy_init_cke (phy_init_cke),
+ .phy_init_data_sel (phy_init_data_sel),
+ .odt (odt),
+ .ddr_addr (ddr_addr),
+ .ddr_ba (ddr_ba),
+ .ddr_ras_n (ddr_ras_n),
+ .ddr_cas_n (ddr_cas_n),
+ .ddr_we_n (ddr_we_n),
+ .ddr_cke (ddr_cke),
+ .ddr_cs_n (ddr_cs_n),
+ .ddr_odt (ddr_odt)
+ );
+
+ ddr2_phy_init #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .CKE_WIDTH (CKE_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .CS_BITS (CS_BITS),
+ .CS_NUM (CS_NUM),
+ .DQ_WIDTH (DQ_WIDTH),
+ .ODT_WIDTH (ODT_WIDTH),
+ .ROW_WIDTH (ROW_WIDTH),
+ .ADDITIVE_LAT (ADDITIVE_LAT),
+ .BURST_LEN (BURST_LEN),
+ .BURST_TYPE (BURST_TYPE),
+ .TWO_T_TIME_EN(TWO_T_TIME_EN),
+ .CAS_LAT (CAS_LAT),
+ .ODT_TYPE (ODT_TYPE),
+ .REDUCE_DRV (REDUCE_DRV),
+ .REG_ENABLE (REG_ENABLE),
+ .TWR (TWR),
+ .CLK_PERIOD (CLK_PERIOD),
+ .DDR_TYPE (DDR_TYPE),
+ .SIM_ONLY (SIM_ONLY)
+ )
+ u_phy_init
+ (
+ .clk0 (clk0),
+ .clkdiv0 (clkdiv0),
+ .rst0 (rst0),
+ .rstdiv0 (rstdiv0),
+ .calib_done (calib_done),
+ .ctrl_ref_flag (ctrl_ref_flag),
+ .calib_ref_req (calib_ref_req),
+ .calib_start (calib_start),
+ .calib_ref_done (calib_ref_done),
+ .phy_init_wren (phy_init_wren),
+ .phy_init_rden (phy_init_rden),
+ .phy_init_addr (phy_init_addr),
+ .phy_init_ba (phy_init_ba),
+ .phy_init_ras_n (phy_init_ras_n),
+ .phy_init_cas_n (phy_init_cas_n),
+ .phy_init_we_n (phy_init_we_n),
+ .phy_init_cs_n (phy_init_cs_n),
+ .phy_init_cke (phy_init_cke),
+ .phy_init_done (phy_init_done),
+ .phy_init_data_sel (phy_init_data_sel)
+ );
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_init.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_init.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_init.v (revision 3)
@@ -0,0 +1,1219 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_phy_init.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Thu Aug 24 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+//Reference:
+// This module is the intialization control logic of the memory interface.
+// All commands are issued from here acoording to the burst, CAS Latency and
+// the user commands.
+//Revision History:
+// Rev 1.1 - Localparam WR_RECOVERY added and mapped to
+// load mode register. PK. 14/7/08
+// Rev 1.2 - To issue an Auto Refresh command to each chip during various
+// calibration stages logic modified. PK. 08/10/08
+// Rev 1.3 - Retain current data pattern for stage 4 calibration, and create
+// new pattern for stage 4. RC. 09/21/09.
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_init #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter CKE_WIDTH = 1,
+ parameter COL_WIDTH = 10,
+ parameter CS_BITS = 0,
+ parameter CS_NUM = 1,
+ parameter DQ_WIDTH = 72,
+ parameter ODT_WIDTH = 1,
+ parameter ROW_WIDTH = 14,
+ parameter ADDITIVE_LAT = 0,
+ parameter BURST_LEN = 4,
+ parameter TWO_T_TIME_EN = 0,
+ parameter BURST_TYPE = 0,
+ parameter CAS_LAT = 5,
+ parameter ODT_TYPE = 1,
+ parameter REDUCE_DRV = 0,
+ parameter REG_ENABLE = 1,
+ parameter TWR = 15000,
+ parameter CLK_PERIOD = 3000,
+ parameter DDR_TYPE = 1,
+ parameter SIM_ONLY = 0
+ )
+ (
+ input clk0,
+ input clkdiv0,
+ input rst0,
+ input rstdiv0,
+ input [3:0] calib_done,
+ input ctrl_ref_flag,
+ input calib_ref_req,
+ output reg [3:0] calib_start,
+ output reg calib_ref_done,
+ output reg phy_init_wren,
+ output reg phy_init_rden,
+ output [ROW_WIDTH-1:0] phy_init_addr,
+ output [BANK_WIDTH-1:0] phy_init_ba,
+ output phy_init_ras_n,
+ output phy_init_cas_n,
+ output phy_init_we_n,
+ output [CS_NUM-1:0] phy_init_cs_n,
+ output [CKE_WIDTH-1:0] phy_init_cke,
+ output reg phy_init_done,
+ output phy_init_data_sel
+ );
+
+ // time to wait between consecutive commands in PHY_INIT - this is a
+ // generic number, and must be large enough to account for worst case
+ // timing parameter (tRFC - refresh-to-active) across all memory speed
+ // grades and operating frequencies. Expressed in CLKDIV clock cycles.
+ localparam CNTNEXT_CMD = 7'b1111111;
+ // time to wait between read and read or precharge for stage 3 & 4
+ // the larger CNTNEXT_CMD can also be used, use smaller number to
+ // speed up calibration - avoid tRAS violation, and speeds up simulation
+ localparam CNTNEXT_RD = 4'b1111;
+
+ // Write recovery (WR) time - is defined by
+ // tWR (in nanoseconds) by tCK (in nanoseconds) and rounding up a
+ // noninteger value to the next integer
+ localparam integer WR_RECOVERY = ((TWR + CLK_PERIOD) - 1)/CLK_PERIOD;
+ localparam CS_BITS_FIX = (CS_BITS == 0) ? 1 : CS_BITS;
+
+ localparam INIT_CAL1_READ = 5'h00;
+ localparam INIT_CAL2_READ = 5'h01;
+ localparam INIT_CAL3_READ = 5'h02;
+ localparam INIT_CAL4_READ = 5'h03;
+ localparam INIT_CAL1_WRITE = 5'h04;
+ localparam INIT_CAL2_WRITE = 5'h05;
+ localparam INIT_CAL3_WRITE = 5'h06;
+ localparam INIT_DUMMY_ACTIVE_WAIT = 5'h07;
+ localparam INIT_PRECHARGE = 5'h08;
+ localparam INIT_LOAD_MODE = 5'h09;
+ localparam INIT_AUTO_REFRESH = 5'h0A;
+ localparam INIT_IDLE = 5'h0B;
+ localparam INIT_CNT_200 = 5'h0C;
+ localparam INIT_CNT_200_WAIT = 5'h0D;
+ localparam INIT_PRECHARGE_WAIT = 5'h0E;
+ localparam INIT_MODE_REGISTER_WAIT = 5'h0F;
+ localparam INIT_AUTO_REFRESH_WAIT = 5'h10;
+ localparam INIT_DEEP_MEMORY_ST = 5'h11;
+ localparam INIT_DUMMY_ACTIVE = 5'h12;
+ localparam INIT_CAL1_WRITE_READ = 5'h13;
+ localparam INIT_CAL1_READ_WAIT = 5'h14;
+ localparam INIT_CAL2_WRITE_READ = 5'h15;
+ localparam INIT_CAL2_READ_WAIT = 5'h16;
+ localparam INIT_CAL3_WRITE_READ = 5'h17;
+ localparam INIT_CAL3_READ_WAIT = 5'h18;
+ localparam INIT_CAL4_READ_WAIT = 5'h19;
+ localparam INIT_CALIB_REF = 5'h1A;
+ localparam INIT_ZQCL = 5'h1B;
+ localparam INIT_WAIT_DLLK_ZQINIT = 5'h1C;
+ localparam INIT_CAL4_WRITE = 5'h1D; // MIG 3.3: New state
+ localparam INIT_CAL4_WRITE_READ = 5'h1E; // MIG 3.3: New state
+
+ localparam INIT_CNTR_INIT = 4'h0;
+ localparam INIT_CNTR_PRECH_1 = 4'h1;
+ localparam INIT_CNTR_EMR2_INIT = 4'h2;
+ localparam INIT_CNTR_EMR3_INIT = 4'h3;
+ localparam INIT_CNTR_EMR_EN_DLL = 4'h4;
+ localparam INIT_CNTR_MR_RST_DLL = 4'h5;
+ localparam INIT_CNTR_CNT_200_WAIT = 4'h6;
+ localparam INIT_CNTR_PRECH_2 = 4'h7;
+ localparam INIT_CNTR_AR_1 = 4'h8;
+ localparam INIT_CNTR_AR_2 = 4'h9;
+ localparam INIT_CNTR_MR_ACT_DLL = 4'hA;
+ localparam INIT_CNTR_EMR_DEF_OCD = 4'hB;
+ localparam INIT_CNTR_EMR_EXIT_OCD = 4'hC;
+ localparam INIT_CNTR_DEEP_MEM = 4'hD;
+ // MIG 3.3: Remove extra precharge occurring at end of calibration
+// localparam INIT_CNTR_PRECH_3 = 4'hE;
+// localparam INIT_CNTR_DONE = 4'hF;
+ localparam INIT_CNTR_DONE = 4'hE;
+
+ localparam DDR1 = 0;
+ localparam DDR2 = 1;
+ localparam DDR3 = 2;
+
+ reg [CS_BITS_FIX :0] auto_cnt_r;
+ reg [1:0] burst_addr_r;
+ reg [1:0] burst_cnt_r;
+ wire [1:0] burst_val;
+ wire cal_read;
+ wire cal_write;
+ wire cal_write_read;
+ reg cal1_started_r;
+ reg cal2_started_r;
+ reg cal4_started_r;
+ reg [3:0] calib_done_r;
+ reg calib_ref_req_posedge;
+ reg calib_ref_req_r;
+ reg [15:0] calib_start_shift0_r;
+ reg [15:0] calib_start_shift1_r;
+ reg [15:0] calib_start_shift2_r;
+ reg [15:0] calib_start_shift3_r;
+ reg [1:0] chip_cnt_r;
+ reg [4:0] cke_200us_cnt_r;
+ reg cke_200us_cnt_en_r;
+ reg [7:0] cnt_200_cycle_r;
+ reg cnt_200_cycle_done_r;
+ reg [6:0] cnt_cmd_r;
+ reg cnt_cmd_ok_r;
+ reg [3:0] cnt_rd_r;
+ reg cnt_rd_ok_r;
+ reg ctrl_ref_flag_r;
+ reg done_200us_r;
+ reg [ROW_WIDTH-1:0] ddr_addr_r;
+ reg [ROW_WIDTH-1:0] ddr_addr_r1;
+ reg [BANK_WIDTH-1:0] ddr_ba_r;
+ reg [BANK_WIDTH-1:0] ddr_ba_r1;
+ reg ddr_cas_n_r;
+ reg ddr_cas_n_r1;
+ reg [CKE_WIDTH-1:0] ddr_cke_r;
+ reg [CS_NUM-1:0] ddr_cs_n_r;
+ reg [CS_NUM-1:0] ddr_cs_n_r1;
+ reg [CS_NUM-1:0] ddr_cs_disable_r;
+ reg ddr_ras_n_r;
+ reg ddr_ras_n_r1;
+ reg ddr_we_n_r;
+ reg ddr_we_n_r1;
+ wire [15:0] ext_mode_reg;
+ reg [3:0] init_cnt_r;
+ reg init_done_r;
+ reg [4:0] init_next_state;
+ reg [4:0] init_state_r;
+ reg [4:0] init_state_r1;
+ reg [4:0] init_state_r1_2t;
+ reg [4:0] init_state_r2;
+ wire [15:0] load_mode_reg;
+ wire [15:0] load_mode_reg0;
+ wire [15:0] load_mode_reg1;
+ wire [15:0] load_mode_reg2;
+ wire [15:0] load_mode_reg3;
+ reg phy_init_done_r;
+ reg phy_init_done_r1;
+ reg phy_init_done_r2;
+ reg phy_init_done_r3;
+ reg refresh_req;
+ wire [3:0] start_cal;
+
+ //***************************************************************************
+
+ //*****************************************************************
+ // DDR1 and DDR2 Load mode register
+ // Mode Register (MR):
+ // [15:14] - unused - 00
+ // [13] - reserved - 0
+ // [12] - Power-down mode - 0 (normal)
+ // [11:9] - write recovery - for Auto Precharge (tWR/tCK)
+ // [8] - DLL reset - 0 or 1
+ // [7] - Test Mode - 0 (normal)
+ // [6:4] - CAS latency - CAS_LAT
+ // [3] - Burst Type - BURST_TYPE
+ // [2:0] - Burst Length - BURST_LEN
+ //*****************************************************************
+
+ generate
+ if (DDR_TYPE == DDR2) begin: gen_load_mode_reg_ddr2
+ assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
+ ((BURST_LEN == 4) ? 3'b010 : 3'b111);
+ assign load_mode_reg[3] = BURST_TYPE;
+ assign load_mode_reg[6:4] = (CAS_LAT == 3) ? 3'b011 :
+ ((CAS_LAT == 4) ? 3'b100 :
+ ((CAS_LAT == 5) ? 3'b101 : 3'b111));
+ assign load_mode_reg[7] = 1'b0;
+ assign load_mode_reg[8] = 1'b0; // init value only (DLL not reset)
+ assign load_mode_reg[11:9] = (WR_RECOVERY == 6) ? 3'b101 :
+ ((WR_RECOVERY == 5) ? 3'b100 :
+ ((WR_RECOVERY == 4) ? 3'b011 :
+ ((WR_RECOVERY == 3) ? 3'b010 :
+ 3'b001)));
+ assign load_mode_reg[15:12] = 4'b000;
+ end else if (DDR_TYPE == DDR1)begin: gen_load_mode_reg_ddr1
+ assign load_mode_reg[2:0] = (BURST_LEN == 8) ? 3'b011 :
+ ((BURST_LEN == 4) ? 3'b010 :
+ ((BURST_LEN == 2) ? 3'b001 : 3'b111));
+ assign load_mode_reg[3] = BURST_TYPE;
+ assign load_mode_reg[6:4] = (CAS_LAT == 2) ? 3'b010 :
+ ((CAS_LAT == 3) ? 3'b011 :
+ ((CAS_LAT == 25) ? 3'b110 : 3'b111));
+ assign load_mode_reg[12:7] = 6'b000000; // init value only
+ assign load_mode_reg[15:13] = 3'b000;
+ end
+ endgenerate
+
+ //*****************************************************************
+ // DDR1 and DDR2 ext mode register
+ // Extended Mode Register (MR):
+ // [15:14] - unused - 00
+ // [13] - reserved - 0
+ // [12] - output enable - 0 (enabled)
+ // [11] - RDQS enable - 0 (disabled)
+ // [10] - DQS# enable - 0 (enabled)
+ // [9:7] - OCD Program - 111 or 000 (first 111, then 000 during init)
+ // [6] - RTT[1] - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
+ // [5:3] - Additive CAS - ADDITIVE_CAS
+ // [2] - RTT[0]
+ // [1] - Output drive - REDUCE_DRV (= 0(full), = 1 (reduced)
+ // [0] - DLL enable - 0 (normal)
+ //*****************************************************************
+
+ generate
+ if (DDR_TYPE == DDR2) begin: gen_ext_mode_reg_ddr2
+ assign ext_mode_reg[0] = 1'b0;
+ assign ext_mode_reg[1] = REDUCE_DRV;
+ assign ext_mode_reg[2] = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
+ 1'b1 : 1'b0;
+ assign ext_mode_reg[5:3] = (ADDITIVE_LAT == 0) ? 3'b000 :
+ ((ADDITIVE_LAT == 1) ? 3'b001 :
+ ((ADDITIVE_LAT == 2) ? 3'b010 :
+ ((ADDITIVE_LAT == 3) ? 3'b011 :
+ ((ADDITIVE_LAT == 4) ? 3'b100 :
+ 3'b111))));
+ assign ext_mode_reg[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
+ 1'b1 : 1'b0;
+ assign ext_mode_reg[9:7] = 3'b000;
+ assign ext_mode_reg[10] = 1'b0;
+ assign ext_mode_reg[15:10] = 6'b000000;
+ end else if (DDR_TYPE == DDR1) begin: gen_ext_mode_reg_ddr1
+ assign ext_mode_reg[0] = 1'b0;
+ assign ext_mode_reg[1] = REDUCE_DRV;
+ assign ext_mode_reg[12:2] = 11'b00000000000;
+ assign ext_mode_reg[15:13] = 3'b000;
+ end
+ endgenerate
+
+ //*****************************************************************
+ // DDR3 Load mode reg0
+ // Mode Register (MR0):
+ // [15:13] - unused - 000
+ // [12] - Precharge Power-down DLL usage - 0 (DLL frozen, slow-exit),
+ // 1 (DLL maintained)
+ // [11:9] - write recovery for Auto Precharge (tWR/tCK = 6)
+ // [8] - DLL reset - 0 or 1
+ // [7] - Test Mode - 0 (normal)
+ // [6:4],[2] - CAS latency - CAS_LAT
+ // [3] - Burst Type - BURST_TYPE
+ // [1:0] - Burst Length - BURST_LEN
+ //*****************************************************************
+
+ generate
+ if (DDR_TYPE == DDR3) begin: gen_load_mode_reg0_ddr3
+ assign load_mode_reg0[1:0] = (BURST_LEN == 8) ? 2'b00 :
+ ((BURST_LEN == 4) ? 2'b10 : 2'b11);
+ // Part of CAS latency. This bit is '0' for all CAS latencies
+ assign load_mode_reg0[2] = 1'b0;
+ assign load_mode_reg0[3] = BURST_TYPE;
+ assign load_mode_reg0[6:4] = (CAS_LAT == 5) ? 3'b001 :
+ (CAS_LAT == 6) ? 3'b010 : 3'b111;
+ assign load_mode_reg0[7] = 1'b0;
+ // init value only (DLL reset)
+ assign load_mode_reg0[8] = 1'b1;
+ assign load_mode_reg0[11:9] = 3'b010;
+ // Precharge Power-Down DLL 'slow-exit'
+ assign load_mode_reg0[12] = 1'b0;
+ assign load_mode_reg0[15:13] = 3'b000;
+ end
+ endgenerate
+
+ //*****************************************************************
+ // DDR3 Load mode reg1
+ // Mode Register (MR1):
+ // [15:13] - unused - 00
+ // [12] - output enable - 0 (enabled for DQ, DQS, DQS#)
+ // [11] - TDQS enable - 0 (TDQS disabled and DM enabled)
+ // [10] - reserved - 0 (must be '0')
+ // [9] - RTT[2] - 0
+ // [8] - reserved - 0 (must be '0')
+ // [7] - write leveling - 0 (disabled), 1 (enabled)
+ // [6] - RTT[1] - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
+ // [5] - Output driver impedance[1] - 0 (RZQ/6 and RZQ/7)
+ // [4:3] - Additive CAS - ADDITIVE_CAS
+ // [2] - RTT[0]
+ // [1] - Output driver impedance[0] - 0(RZQ/6), or 1 (RZQ/7)
+ // [0] - DLL enable - 0 (normal)
+ //*****************************************************************
+
+ generate
+ if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg1_ddr3
+ // DLL enabled during Imitialization
+ assign load_mode_reg1[0] = 1'b0;
+ // RZQ/6
+ assign load_mode_reg1[1] = REDUCE_DRV;
+ assign load_mode_reg1[2] = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
+ 1'b1 : 1'b0;
+ assign load_mode_reg1[4:3] = (ADDITIVE_LAT == 0) ? 2'b00 :
+ ((ADDITIVE_LAT == 1) ? 2'b01 :
+ ((ADDITIVE_LAT == 2) ? 2'b10 :
+ 3'b111));
+ // RZQ/6
+ assign load_mode_reg1[5] = 1'b0;
+ assign load_mode_reg1[6] = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
+ 1'b1 : 1'b0;
+ // Make zero WRITE_LEVEL
+ assign load_mode_reg1[7] = 0;
+ assign load_mode_reg1[8] = 1'b0;
+ assign load_mode_reg1[9] = 1'b0;
+ assign load_mode_reg1[10] = 1'b0;
+ assign load_mode_reg1[15:11] = 5'b00000;
+ end
+ endgenerate
+
+ //*****************************************************************
+ // DDR3 Load mode reg2
+ // Mode Register (MR2):
+ // [15:11] - unused - 00
+ // [10:9] - RTT_WR - 00 (Dynamic ODT off)
+ // [8] - reserved - 0 (must be '0')
+ // [7] - self-refresh temperature range -
+ // 0 (normal), 1 (extended)
+ // [6] - Auto Self-Refresh - 0 (manual), 1(auto)
+ // [5:3] - CAS Write Latency (CWL) -
+ // 000 (5 for 400 MHz device),
+ // 001 (6 for 400 MHz to 533 MHz devices),
+ // 010 (7 for 533 MHz to 667 MHz devices),
+ // 011 (8 for 667 MHz to 800 MHz)
+ // [2:0] - Partial Array Self-Refresh (Optional) -
+ // 000 (full array)
+ //*****************************************************************
+
+ generate
+ if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg2_ddr3
+ assign load_mode_reg2[2:0] = 3'b000;
+ assign load_mode_reg2[5:3] = (CAS_LAT == 5) ? 3'b000 :
+ (CAS_LAT == 6) ? 3'b001 : 3'b111;
+ assign load_mode_reg2[6] = 1'b0; // Manual Self-Refresh
+ assign load_mode_reg2[7] = 1'b0;
+ assign load_mode_reg2[8] = 1'b0;
+ assign load_mode_reg2[10:9] = 2'b00;
+ assign load_mode_reg2[15:11] = 5'b00000;
+ end
+ endgenerate
+
+ //*****************************************************************
+ // DDR3 Load mode reg3
+ // Mode Register (MR3):
+ // [15:3] - unused - All zeros
+ // [2] - MPR Operation - 0(normal operation), 1(data flow from MPR)
+ // [1:0] - MPR location - 00 (Predefined pattern)
+ //*****************************************************************
+
+ generate
+ if (DDR_TYPE == DDR3)begin: gen_ext_mode_reg3_ddr3
+ assign load_mode_reg3[1:0] = 2'b00;
+ assign load_mode_reg3[2] = 1'b0;
+ assign load_mode_reg3[15:3] = 13'b0000000000000;
+ end
+ endgenerate
+
+ //***************************************************************************
+ // Logic for calibration start, and for auto-refresh during cal request
+ // CALIB_REF_REQ is used by calibration logic to request auto-refresh
+ // durign calibration (used to avoid tRAS violation is certain calibration
+ // stages take a long time). Once the auto-refresh is complete and cal can
+ // be resumed, CALIB_REF_DONE is asserted by PHY_INIT.
+ //***************************************************************************
+
+ // generate pulse for each of calibration start controls
+ assign start_cal[0] = ((init_state_r1 == INIT_CAL1_READ) &&
+ (init_state_r2 != INIT_CAL1_READ));
+ assign start_cal[1] = ((init_state_r1 == INIT_CAL2_READ) &&
+ (init_state_r2 != INIT_CAL2_READ));
+ assign start_cal[2] = ((init_state_r1 == INIT_CAL3_READ) &&
+ (init_state_r2 == INIT_CAL3_WRITE_READ));
+ assign start_cal[3] = ((init_state_r1 == INIT_CAL4_READ) &&
+ (init_state_r2 != INIT_CAL4_READ));
+ // MIG 3.3: Change to accomodate FSM changes related to stage 4 calibration
+// (init_state_r2 == INIT_CAL4_WRITE_READ));
+
+ // Generate positive-edge triggered, latched signal to force initialization
+ // to pause calibration, and to issue auto-refresh. Clear flag as soon as
+ // refresh initiated
+ always @(posedge clkdiv0)
+ if (rstdiv0) begin
+ calib_ref_req_r <= 1'b0;
+ calib_ref_req_posedge <= 1'b0;
+ refresh_req <= 1'b0;
+ end else begin
+ calib_ref_req_r <= calib_ref_req;
+ calib_ref_req_posedge <= calib_ref_req & ~calib_ref_req_r;
+ if (init_state_r1 == INIT_AUTO_REFRESH)
+ refresh_req <= 1'b0;
+ else if (calib_ref_req_posedge)
+ refresh_req <= 1'b1;
+ end
+
+ // flag to tell cal1 calibration was started.
+ // This flag is used for cal1 auto refreshes
+ // some of these bits may not be needed - only needed for those stages that
+ // need refreshes within the stage (i.e. very long stages)
+ always @(posedge clkdiv0)
+ if (rstdiv0) begin
+ cal1_started_r <= 1'b0;
+ cal2_started_r <= 1'b0;
+ cal4_started_r <= 1'b0;
+ end else begin
+ if (calib_start[0])
+ cal1_started_r <= 1'b1;
+ if (calib_start[1])
+ cal2_started_r <= 1'b1;
+ if (calib_start[3])
+ cal4_started_r <= 1'b1;
+ end
+
+ // Delay start of each calibration by 16 clock cycles to
+ // ensure that when calibration logic begins, that read data is already
+ // appearing on the bus. Don't really need it, it's more for simulation
+ // purposes. Each circuit should synthesize using an SRL16.
+ // In first stage of calibration periodic auto refreshes
+ // will be issued to meet memory timing. calib_start_shift0_r[15] will be
+ // asserted more than once.calib_start[0] is anded with cal1_started_r so
+ // that it is asserted only once. cal1_refresh_done is anded with
+ // cal1_started_r so that it is asserted after the auto refreshes.
+ always @(posedge clkdiv0) begin
+ calib_start_shift0_r <= {calib_start_shift0_r[14:0], start_cal[0]};
+ calib_start_shift1_r <= {calib_start_shift1_r[14:0], start_cal[1]};
+ calib_start_shift2_r <= {calib_start_shift2_r[14:0], start_cal[2]};
+ calib_start_shift3_r <= {calib_start_shift3_r[14:0], start_cal[3]};
+ calib_start[0] <= calib_start_shift0_r[15] & ~cal1_started_r;
+ calib_start[1] <= calib_start_shift1_r[15] & ~cal2_started_r;
+ calib_start[2] <= calib_start_shift2_r[15];
+ calib_start[3] <= calib_start_shift3_r[15] & ~cal4_started_r;
+ calib_ref_done <= calib_start_shift0_r[15] |
+ calib_start_shift1_r[15] |
+ calib_start_shift3_r[15];
+ end
+
+ // generate delay for various states that require it (no maximum delay
+ // requirement, make sure that terminal count is large enough to cover
+ // all cases)
+ always @(posedge clkdiv0) begin
+ case (init_state_r)
+ INIT_PRECHARGE_WAIT,
+ INIT_MODE_REGISTER_WAIT,
+ INIT_AUTO_REFRESH_WAIT,
+ INIT_DUMMY_ACTIVE_WAIT,
+ INIT_CAL1_WRITE_READ,
+ INIT_CAL1_READ_WAIT,
+ INIT_CAL2_WRITE_READ,
+ INIT_CAL2_READ_WAIT,
+ INIT_CAL3_WRITE_READ,
+ INIT_CAL4_WRITE_READ :
+ cnt_cmd_r <= cnt_cmd_r + 1;
+ default:
+ cnt_cmd_r <= 7'b0000000;
+ endcase
+ end
+
+ // assert when count reaches the value
+ always @(posedge clkdiv0) begin
+ if(cnt_cmd_r == CNTNEXT_CMD)
+ cnt_cmd_ok_r <= 1'b1;
+ else
+ cnt_cmd_ok_r <= 1'b0;
+ end
+
+ always @(posedge clkdiv0) begin
+ case (init_state_r)
+ INIT_CAL3_READ_WAIT,
+ INIT_CAL4_READ_WAIT:
+ cnt_rd_r <= cnt_rd_r + 1;
+ default:
+ cnt_rd_r <= 4'b0000;
+ endcase
+ end
+
+ always @(posedge clkdiv0) begin
+ if(cnt_rd_r == CNTNEXT_RD)
+ cnt_rd_ok_r <= 1'b1;
+ else
+ cnt_rd_ok_r <= 1'b0;
+ end
+
+ //***************************************************************************
+ // Initial delay after power-on
+ //***************************************************************************
+
+ // register the refresh flag from the controller.
+ // The refresh flag is in full frequency domain - so a pulsed version must
+ // be generated for half freq domain using 2 consecutive full clk cycles
+ // The registered version is used for the 200us counter
+ always @(posedge clk0)
+ ctrl_ref_flag_r <= ctrl_ref_flag;
+ always @(posedge clkdiv0)
+ cke_200us_cnt_en_r <= ctrl_ref_flag || ctrl_ref_flag_r;
+
+ // 200us counter for cke
+ always @(posedge clkdiv0)
+ if (rstdiv0) begin
+ // skip power-up count if only simulating
+ if (SIM_ONLY)
+ cke_200us_cnt_r <= 5'b00001;
+ else
+ cke_200us_cnt_r <= 5'd27;
+ end else if (cke_200us_cnt_en_r)
+ cke_200us_cnt_r <= cke_200us_cnt_r - 1;
+
+ always @(posedge clkdiv0)
+ if (rstdiv0)
+ done_200us_r <= 1'b0;
+ else if (!done_200us_r)
+ done_200us_r <= (cke_200us_cnt_r == 5'b00000);
+
+ // 200 clocks counter - count value : h'64 required for initialization
+ // Counts 100 divided by two clocks
+ always @(posedge clkdiv0)
+ if (rstdiv0 || (init_state_r == INIT_CNT_200))
+ cnt_200_cycle_r <= 8'h64;
+ else if (init_state_r == INIT_ZQCL) // ddr3
+ cnt_200_cycle_r <= 8'hC8;
+ else if (cnt_200_cycle_r != 8'h00)
+ cnt_200_cycle_r <= cnt_200_cycle_r - 1;
+
+ always @(posedge clkdiv0)
+ if (rstdiv0 || (init_state_r == INIT_CNT_200)
+ || (init_state_r == INIT_ZQCL))
+ cnt_200_cycle_done_r <= 1'b0;
+ else if (cnt_200_cycle_r == 8'h00)
+ cnt_200_cycle_done_r <= 1'b1;
+
+ //*****************************************************************
+ // handle deep memory configuration:
+ // During initialization: Repeat initialization sequence once for each
+ // chip select. Note that we could perform initalization for all chip
+ // selects simulataneously. Probably fine - any potential SI issues with
+ // auto refreshing all chip selects at once?
+ // Once initialization complete, assert only CS[1] for calibration.
+ //*****************************************************************
+
+ always @(posedge clkdiv0)
+ if (rstdiv0) begin
+ chip_cnt_r <= 2'b00;
+ end else if (init_state_r == INIT_DEEP_MEMORY_ST) begin
+ if (chip_cnt_r != CS_NUM)
+ chip_cnt_r <= chip_cnt_r + 1;
+ else
+ chip_cnt_r <= 2'b00;
+ // MIG 2.4: Modified to issue an Auto Refresh commmand
+ // to each chip select during various calibration stages
+ end else if (init_state_r == INIT_PRECHARGE && init_done_r) begin
+ chip_cnt_r <= 2'b00;
+ end else if (init_state_r1 == INIT_AUTO_REFRESH && init_done_r) begin
+ if (chip_cnt_r < (CS_NUM-1))
+ chip_cnt_r <= chip_cnt_r + 1;
+ end
+
+ // keep track of which chip selects got auto-refreshed (avoid auto-refreshing
+ // all CS's at once to avoid current spike)
+ always @(posedge clkdiv0)begin
+ if (rstdiv0 || init_state_r == INIT_PRECHARGE)
+ auto_cnt_r <= 'd0;
+ else if (init_state_r == INIT_AUTO_REFRESH && init_done_r) begin
+ if (auto_cnt_r < CS_NUM)
+ auto_cnt_r <= auto_cnt_r + 1;
+ end
+ end
+
+ always @(posedge clkdiv0)
+ if (rstdiv0) begin
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ end else begin
+ ddr_cs_n_r <= {CS_NUM{1'b1}};
+ if ((init_state_r == INIT_DUMMY_ACTIVE) ||
+ ((init_state_r == INIT_PRECHARGE) && (~init_done_r))||
+ (init_state_r == INIT_LOAD_MODE) ||
+ (init_state_r == INIT_AUTO_REFRESH) ||
+ (init_state_r == INIT_ZQCL ) ||
+ (((init_state_r == INIT_CAL1_READ) ||
+ (init_state_r == INIT_CAL2_READ) ||
+ (init_state_r == INIT_CAL3_READ) ||
+ (init_state_r == INIT_CAL4_READ) ||
+ (init_state_r == INIT_CAL1_WRITE) ||
+ (init_state_r == INIT_CAL2_WRITE) ||
+ (init_state_r == INIT_CAL3_WRITE) ||
+ (init_state_r == INIT_CAL4_WRITE)) && (burst_cnt_r == 2'b00)))
+ ddr_cs_n_r[chip_cnt_r] <= 1'b0;
+ else if (init_state_r == INIT_PRECHARGE)
+ ddr_cs_n_r <= {CS_NUM{1'b0}};
+ else
+ ddr_cs_n_r[chip_cnt_r] <= 1'b1;
+ end
+
+ //***************************************************************************
+ // Write/read burst logic
+ //***************************************************************************
+
+ assign cal_write = ((init_state_r == INIT_CAL1_WRITE) ||
+ (init_state_r == INIT_CAL2_WRITE) ||
+ (init_state_r == INIT_CAL3_WRITE) ||
+ (init_state_r == INIT_CAL4_WRITE));
+ assign cal_read = ((init_state_r == INIT_CAL1_READ) ||
+ (init_state_r == INIT_CAL2_READ) ||
+ (init_state_r == INIT_CAL3_READ) ||
+ (init_state_r == INIT_CAL4_READ));
+ assign cal_write_read = ((init_state_r == INIT_CAL1_READ) ||
+ (init_state_r == INIT_CAL2_READ) ||
+ (init_state_r == INIT_CAL3_READ) ||
+ (init_state_r == INIT_CAL4_READ) ||
+ (init_state_r == INIT_CAL1_WRITE) ||
+ (init_state_r == INIT_CAL2_WRITE) ||
+ (init_state_r == INIT_CAL3_WRITE) ||
+ (init_state_r == INIT_CAL4_WRITE));
+
+ assign burst_val = (BURST_LEN == 4) ? 2'b00 :
+ (BURST_LEN == 8) ? 2'b01 : 2'b00;
+
+ // keep track of current address - need this if burst length < 8 for
+ // stage 2-4 calibration writes and reads. Make sure value always gets
+ // initialized to 0 before we enter write/read state. This is used to
+ // keep track of when another burst must be issued
+ always @(posedge clkdiv0)
+ if (cal_write_read)
+ burst_addr_r <= burst_addr_r + 2;
+ else
+ burst_addr_r <= 2'b00;
+
+ // write/read burst count
+ always @(posedge clkdiv0)
+ if (cal_write_read)
+ if (burst_cnt_r == 2'b00)
+ burst_cnt_r <= burst_val;
+ else // SHOULD THIS BE -2 CHECK THIS LOGIC
+ burst_cnt_r <= burst_cnt_r - 1;
+ else
+ burst_cnt_r <= 2'b00;
+
+ // indicate when a write is occurring
+ always @(posedge clkdiv0)
+ // MIG 2.1: Remove (burst_addr_r<4) term - not used
+ // phy_init_wren <= cal_write && (burst_addr_r < 3'd4);
+ phy_init_wren <= cal_write;
+
+ // used for read enable calibration, pulse to indicate when read issued
+ always @(posedge clkdiv0)
+ // MIG 2.1: Remove (burst_addr_r<4) term - not used
+ // phy_init_rden <= cal_read && (burst_addr_r < 3'd4);
+ phy_init_rden <= cal_read;
+
+ //***************************************************************************
+ // Initialization state machine
+ //***************************************************************************
+
+ always @(posedge clkdiv0)
+ // every time we need to initialize another rank of memory, need to
+ // reset init count, and repeat the entire initialization (but not
+ // calibration) sequence
+ if (rstdiv0 || (init_state_r == INIT_DEEP_MEMORY_ST))
+ init_cnt_r <= INIT_CNTR_INIT;
+ else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_PRECHARGE) &&
+ (init_cnt_r == INIT_CNTR_PRECH_1))
+ // skip EMR(2) and EMR(3) register loads
+ init_cnt_r <= INIT_CNTR_EMR_EN_DLL;
+ else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_LOAD_MODE) &&
+ (init_cnt_r == INIT_CNTR_MR_ACT_DLL))
+ // skip OCD calibration for DDR1
+ init_cnt_r <= INIT_CNTR_DEEP_MEM;
+ else if ((DDR_TYPE == DDR3) && (init_state_r == INIT_ZQCL))
+ // skip states for DDR3
+ init_cnt_r <= INIT_CNTR_DEEP_MEM;
+ else if ((init_state_r == INIT_LOAD_MODE) ||
+ ((init_state_r == INIT_PRECHARGE) &&
+ (init_state_r1 != INIT_CALIB_REF)) ||
+ ((init_state_r == INIT_AUTO_REFRESH) && (~init_done_r)) ||
+ (init_state_r == INIT_CNT_200) ||
+ // MIG 3.3: Added increment when starting calibration
+ ((init_state_r == INIT_DUMMY_ACTIVE) &&
+ (init_state_r1 == INIT_IDLE)))
+ init_cnt_r <= init_cnt_r + 1;
+
+ always @(posedge clkdiv0) begin
+ if ((init_state_r == INIT_IDLE) && (init_cnt_r == INIT_CNTR_DONE)) begin
+ phy_init_done_r <= 1'b1;
+ end else
+ phy_init_done_r <= 1'b0;
+ end
+
+ // phy_init_done to the controller and the user interface.
+ // It is delayed by four clocks to account for the
+ // multi cycle path constraint to the (phy_init_data_sel)
+ // to the phy layer.
+ always @(posedge clkdiv0) begin
+ phy_init_done_r1 <= phy_init_done_r;
+ phy_init_done_r2 <= phy_init_done_r1;
+ phy_init_done_r3 <= phy_init_done_r2;
+ phy_init_done <= phy_init_done_r3;
+ end
+
+ // Instantiate primitive to allow this flop to be attached to multicycle
+ // path constraint in UCF. This signal goes to PHY_WRITE and PHY_CTL_IO
+ // datapath logic only. Because it is a multi-cycle path, it can be
+ // clocked by either CLKDIV0 or CLK0.
+ FDRSE u_ff_phy_init_data_sel
+ (
+ .Q (phy_init_data_sel),
+ .C (clkdiv0),
+ .CE (1'b1),
+ .D (phy_init_done_r1),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve=1 */
+ /* synthesis syn_replicate = 0 */;
+
+ //synthesis translate_off
+ always @(posedge calib_done[0])
+ $display ("First Stage Calibration completed at time %t", $time);
+
+ always @(posedge calib_done[1])
+ $display ("Second Stage Calibration completed at time %t", $time);
+
+ always @(posedge calib_done[2]) begin
+ $display ("Third Stage Calibration completed at time %t", $time);
+ end
+
+ always @(posedge calib_done[3]) begin
+ $display ("Fourth Stage Calibration completed at time %t", $time);
+ $display ("Calibration completed at time %t", $time);
+ end
+ //synthesis translate_on
+
+ always @(posedge clkdiv0) begin
+ if ((init_cnt_r >= INIT_CNTR_DEEP_MEM))begin
+ init_done_r <= 1'b1;
+ end else
+ init_done_r <= 1'b0;
+ end
+
+ //*****************************************************************
+
+ always @(posedge clkdiv0)
+ if (rstdiv0) begin
+ init_state_r <= INIT_IDLE;
+ init_state_r1 <= INIT_IDLE;
+ init_state_r2 <= INIT_IDLE;
+ calib_done_r <= 4'b0000;
+ end else begin
+ init_state_r <= init_next_state;
+ init_state_r1 <= init_state_r;
+ init_state_r2 <= init_state_r1;
+ calib_done_r <= calib_done; // register for timing
+ end
+
+ always @(*) begin
+ init_next_state = init_state_r;
+ (* full_case, parallel_case *) case (init_state_r)
+ INIT_IDLE: begin
+ if (done_200us_r) begin
+ (* parallel_case *) case (init_cnt_r)
+ INIT_CNTR_INIT:
+ init_next_state = INIT_CNT_200;
+ INIT_CNTR_PRECH_1:
+ init_next_state = INIT_PRECHARGE;
+ INIT_CNTR_EMR2_INIT:
+ init_next_state = INIT_LOAD_MODE; // EMR(2)
+ INIT_CNTR_EMR3_INIT:
+ init_next_state = INIT_LOAD_MODE; // EMR(3);
+ INIT_CNTR_EMR_EN_DLL:
+ init_next_state = INIT_LOAD_MODE; // EMR, enable DLL
+ INIT_CNTR_MR_RST_DLL:
+ init_next_state = INIT_LOAD_MODE; // MR, reset DLL
+ INIT_CNTR_CNT_200_WAIT:begin
+ if(DDR_TYPE == DDR3)
+ init_next_state = INIT_ZQCL; // DDR3
+ else
+ // Wait 200cc after reset DLL
+ init_next_state = INIT_CNT_200;
+ end
+ INIT_CNTR_PRECH_2:
+ init_next_state = INIT_PRECHARGE;
+ INIT_CNTR_AR_1:
+ init_next_state = INIT_AUTO_REFRESH;
+ INIT_CNTR_AR_2:
+ init_next_state = INIT_AUTO_REFRESH;
+ INIT_CNTR_MR_ACT_DLL:
+ init_next_state = INIT_LOAD_MODE; // MR, unreset DLL
+ INIT_CNTR_EMR_DEF_OCD:
+ init_next_state = INIT_LOAD_MODE; // EMR, OCD default
+ INIT_CNTR_EMR_EXIT_OCD:
+ init_next_state = INIT_LOAD_MODE; // EMR, enable OCD exit
+ INIT_CNTR_DEEP_MEM: begin
+ if ((chip_cnt_r < CS_NUM-1))
+ init_next_state = INIT_DEEP_MEMORY_ST;
+ else if (cnt_200_cycle_done_r)
+ init_next_state = INIT_DUMMY_ACTIVE;
+ else
+ init_next_state = INIT_IDLE;
+ end
+ // MIG 3.3: Remove extra precharge occurring at end of calibration
+// INIT_CNTR_PRECH_3:
+// init_next_state = INIT_PRECHARGE;
+ INIT_CNTR_DONE:
+ init_next_state = INIT_IDLE;
+ default :
+ init_next_state = INIT_IDLE;
+ endcase
+ end
+ end
+ INIT_CNT_200:
+ init_next_state = INIT_CNT_200_WAIT;
+ INIT_CNT_200_WAIT:
+ if (cnt_200_cycle_done_r)
+ init_next_state = INIT_IDLE;
+ INIT_PRECHARGE:
+ init_next_state = INIT_PRECHARGE_WAIT;
+ INIT_PRECHARGE_WAIT:
+ if (cnt_cmd_ok_r)begin
+ if (init_done_r && (!(&calib_done_r)))
+ init_next_state = INIT_AUTO_REFRESH;
+ else
+ init_next_state = INIT_IDLE;
+ end
+ INIT_ZQCL:
+ init_next_state = INIT_WAIT_DLLK_ZQINIT;
+ INIT_WAIT_DLLK_ZQINIT:
+ if (cnt_200_cycle_done_r)
+ init_next_state = INIT_IDLE;
+ INIT_LOAD_MODE:
+ init_next_state = INIT_MODE_REGISTER_WAIT;
+ INIT_MODE_REGISTER_WAIT:
+ if (cnt_cmd_ok_r)
+ init_next_state = INIT_IDLE;
+ INIT_AUTO_REFRESH:
+ init_next_state = INIT_AUTO_REFRESH_WAIT;
+ INIT_AUTO_REFRESH_WAIT:
+ // MIG 2.4: Modified to issue an Auto Refresh commmand
+ // to each chip select during various calibration stages
+ if (auto_cnt_r < CS_NUM && init_done_r) begin
+ if (cnt_cmd_ok_r)
+ init_next_state = INIT_AUTO_REFRESH;
+ end else if (cnt_cmd_ok_r)begin
+ if (init_done_r)
+ init_next_state = INIT_DUMMY_ACTIVE;
+ else
+ init_next_state = INIT_IDLE;
+ end
+ INIT_DEEP_MEMORY_ST:
+ init_next_state = INIT_IDLE;
+ // single row activate. All subsequent calibration writes and
+ // read will take place in this row
+ INIT_DUMMY_ACTIVE:
+ init_next_state = INIT_DUMMY_ACTIVE_WAIT;
+ INIT_DUMMY_ACTIVE_WAIT:
+ if (cnt_cmd_ok_r)begin
+ if (~calib_done_r[0]) begin
+ // if returning to stg1 after refresh, don't need to write
+ if (cal1_started_r)
+ init_next_state = INIT_CAL1_READ;
+ // if first entering stg1, need to write training pattern
+ else
+ init_next_state = INIT_CAL1_WRITE;
+ end else if (~calib_done[1]) begin
+ if (cal2_started_r)
+ init_next_state = INIT_CAL2_READ;
+ else
+ init_next_state = INIT_CAL2_WRITE;
+ end else if (~calib_done_r[2])
+ // Stage 3 only requires a refresh after the entire stage is
+ // finished
+ init_next_state = INIT_CAL3_WRITE;
+ else begin
+ // Stage 4 requires a refresh after every DQS group
+ if (cal4_started_r)
+ init_next_state = INIT_CAL4_READ;
+ else
+ init_next_state = INIT_CAL4_WRITE;
+ end
+ end
+ // Stage 1 calibration (write and continuous read)
+ INIT_CAL1_WRITE:
+ if (burst_addr_r == 2'b10)
+ init_next_state = INIT_CAL1_WRITE_READ;
+ INIT_CAL1_WRITE_READ:
+ if (cnt_cmd_ok_r)
+ init_next_state = INIT_CAL1_READ;
+ INIT_CAL1_READ:
+ // Stage 1 requires inter-stage auto-refresh
+ if (calib_done_r[0] || refresh_req)
+ init_next_state = INIT_CAL1_READ_WAIT;
+ INIT_CAL1_READ_WAIT:
+ if (cnt_cmd_ok_r)
+ init_next_state = INIT_CALIB_REF;
+ // Stage 2 calibration (write and continuous read)
+ INIT_CAL2_WRITE:
+ if (burst_addr_r == 2'b10)
+ init_next_state = INIT_CAL2_WRITE_READ;
+ INIT_CAL2_WRITE_READ:
+ if (cnt_cmd_ok_r)
+ init_next_state = INIT_CAL2_READ;
+ INIT_CAL2_READ:
+ // Stage 2 requires inter-stage auto-refresh
+ if (calib_done_r[1] || refresh_req)
+ init_next_state = INIT_CAL2_READ_WAIT;
+ INIT_CAL2_READ_WAIT:
+ if (cnt_cmd_ok_r)
+ init_next_state = INIT_CALIB_REF;
+ // Stage 3 calibration (write and continuous read)
+ INIT_CAL3_WRITE:
+ if (burst_addr_r == 2'b10)
+ init_next_state = INIT_CAL3_WRITE_READ;
+ INIT_CAL3_WRITE_READ:
+ if (cnt_cmd_ok_r)
+ init_next_state = INIT_CAL3_READ;
+ INIT_CAL3_READ:
+ if (burst_addr_r == 2'b10)
+ init_next_state = INIT_CAL3_READ_WAIT;
+ INIT_CAL3_READ_WAIT: begin
+ if (cnt_rd_ok_r)
+ if (calib_done_r[2]) begin
+ init_next_state = INIT_CALIB_REF;
+ end else
+ init_next_state = INIT_CAL3_READ;
+ end
+ // Stage 4 calibration
+ INIT_CAL4_WRITE:
+ if (burst_addr_r == 2'b10)
+ init_next_state = INIT_CAL4_WRITE_READ;
+ INIT_CAL4_WRITE_READ:
+ if (cnt_cmd_ok_r)
+ init_next_state = INIT_CAL4_READ;
+ INIT_CAL4_READ:
+ if (burst_addr_r == 2'b10)
+ init_next_state = INIT_CAL4_READ_WAIT;
+ INIT_CAL4_READ_WAIT: begin
+ if (cnt_rd_ok_r)
+ // Stage 4 requires inter-stage auto-refresh
+ if (calib_done_r[3] || refresh_req)
+ // MIG 3.3: With removal of extra precharge, proceed to
+ // state CALIB_REF first to avoid incrementing init_cntr
+// init_next_state = INIT_PRECHARGE;
+ init_next_state = INIT_CALIB_REF;
+ else
+ init_next_state = INIT_CAL4_READ;
+ end
+ INIT_CALIB_REF:
+ init_next_state = INIT_PRECHARGE;
+ endcase
+ end
+
+ //***************************************************************************
+ // Memory control/address
+ //***************************************************************************
+
+ always @(posedge clkdiv0)
+ if ((init_state_r == INIT_DUMMY_ACTIVE) ||
+ (init_state_r == INIT_PRECHARGE) ||
+ (init_state_r == INIT_LOAD_MODE) ||
+ (init_state_r == INIT_AUTO_REFRESH)) begin
+ ddr_ras_n_r <= 1'b0;
+ end else begin
+ ddr_ras_n_r <= 1'b1;
+ end
+
+ always @(posedge clkdiv0)
+ if ((init_state_r == INIT_LOAD_MODE) ||
+ (init_state_r == INIT_AUTO_REFRESH) ||
+ (cal_write_read && (burst_cnt_r == 2'b00))) begin
+ ddr_cas_n_r <= 1'b0;
+ end else begin
+ ddr_cas_n_r <= 1'b1;
+ end
+
+ always @(posedge clkdiv0)
+ if ((init_state_r == INIT_LOAD_MODE) ||
+ (init_state_r == INIT_PRECHARGE) ||
+ (init_state_r == INIT_ZQCL) ||
+ (cal_write && (burst_cnt_r == 2'b00)))begin
+ ddr_we_n_r <= 1'b0;
+ end else begin
+ ddr_we_n_r <= 1'b1;
+ end
+
+ //*****************************************************************
+ // memory address during init
+ //*****************************************************************
+
+ always @(posedge clkdiv0) begin
+ if ((init_state_r == INIT_PRECHARGE)
+ || (init_state_r == INIT_ZQCL))begin
+ // Precharge all - set A10 = 1
+ ddr_addr_r <= {ROW_WIDTH{1'b0}};
+ ddr_addr_r[10] <= 1'b1;
+ ddr_ba_r <= {BANK_WIDTH{1'b0}};
+ end else if (init_state_r == INIT_LOAD_MODE) begin
+ ddr_ba_r <= {BANK_WIDTH{1'b0}};
+ ddr_addr_r <= {ROW_WIDTH{1'b0}};
+ case (init_cnt_r)
+ // EMR (2)
+ INIT_CNTR_EMR2_INIT: begin
+ ddr_ba_r[1:0] <= 2'b10;
+ ddr_addr_r <= {ROW_WIDTH{1'b0}};
+ end
+ // EMR (3)
+ INIT_CNTR_EMR3_INIT: begin
+ ddr_ba_r[1:0] <= 2'b11;
+ if(DDR_TYPE == DDR3)
+ ddr_addr_r <= load_mode_reg3[ROW_WIDTH-1:0];
+ else
+ ddr_addr_r <= {ROW_WIDTH{1'b0}};
+ end
+ // EMR write - A0 = 0 for DLL enable
+ INIT_CNTR_EMR_EN_DLL: begin
+ ddr_ba_r[1:0] <= 2'b01;
+ if(DDR_TYPE == DDR3)
+ ddr_addr_r <= load_mode_reg1[ROW_WIDTH-1:0];
+ else
+ ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
+ end
+ // MR write, reset DLL (A8=1)
+ INIT_CNTR_MR_RST_DLL: begin
+ if(DDR_TYPE == DDR3)
+ ddr_addr_r <= load_mode_reg0[ROW_WIDTH-1:0];
+ else
+ ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
+ ddr_ba_r[1:0] <= 2'b00;
+ ddr_addr_r[8] <= 1'b1;
+ end
+ // MR write, unreset DLL (A8=0)
+ INIT_CNTR_MR_ACT_DLL: begin
+ ddr_ba_r[1:0] <= 2'b00;
+ ddr_addr_r <= load_mode_reg[ROW_WIDTH-1:0];
+ end
+ // EMR write, OCD default state
+ INIT_CNTR_EMR_DEF_OCD: begin
+ ddr_ba_r[1:0] <= 2'b01;
+ ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
+ ddr_addr_r[9:7] <= 3'b111;
+ end
+ // EMR write - OCD exit
+ INIT_CNTR_EMR_EXIT_OCD: begin
+ ddr_ba_r[1:0] <= 2'b01;
+ ddr_addr_r <= ext_mode_reg[ROW_WIDTH-1:0];
+ end
+ default: begin
+ ddr_ba_r <= {BANK_WIDTH{1'bx}};
+ ddr_addr_r <= {ROW_WIDTH{1'bx}};
+ end
+ endcase
+ end else if (cal_write_read) begin
+ // when writing or reading for Stages 2-4, since training pattern is
+ // either 4 (stage 2) or 8 (stage 3-4) long, if BURST LEN < 8, then
+ // need to issue multiple bursts to read entire training pattern
+ ddr_addr_r[ROW_WIDTH-1:3] <= {ROW_WIDTH-4{1'b0}};
+ ddr_addr_r[2:0] <= {burst_addr_r, 1'b0};
+ ddr_ba_r <= {BANK_WIDTH-1{1'b0}};
+ end else if (init_state_r == INIT_DUMMY_ACTIVE) begin
+ // all calibration writing read takes place in row 0x0 only
+ ddr_ba_r <= {BANK_WIDTH{1'b0}};
+ ddr_addr_r <= {ROW_WIDTH{1'b0}};
+ end else begin
+ // otherwise, cry me a river
+ ddr_ba_r <= {BANK_WIDTH{1'bx}};
+ ddr_addr_r <= {ROW_WIDTH{1'bx}};
+ end
+ end
+
+ // Keep CKE asserted after initial power-on delay
+ always @(posedge clkdiv0)
+ ddr_cke_r <= {CKE_WIDTH{done_200us_r}};
+
+ // register commands to memory. Two clock cycle delay from state -> output
+ always @(posedge clk0) begin
+ ddr_addr_r1 <= ddr_addr_r;
+ ddr_ba_r1 <= ddr_ba_r;
+ ddr_cas_n_r1 <= ddr_cas_n_r;
+ ddr_ras_n_r1 <= ddr_ras_n_r;
+ ddr_we_n_r1 <= ddr_we_n_r;
+ ddr_cs_n_r1 <= ddr_cs_n_r;
+ end // always @ (posedge clk0)
+
+ always @(posedge clk0)
+ init_state_r1_2t <= init_state_r1;
+
+ // logic to toggle chip select. The chip_select is
+ // clocked of clkdiv0 and will be asserted for
+ // two clock cycles.
+ always @(posedge clk0) begin
+ if(rst0)
+ ddr_cs_disable_r <= {CS_NUM{1'b0}};
+ else begin
+ if(| ddr_cs_disable_r)
+ ddr_cs_disable_r <= {CS_NUM{1'b0}};
+ else begin
+ if (TWO_T_TIME_EN) begin
+ if (init_state_r1_2t == INIT_PRECHARGE && init_done_r)
+ ddr_cs_disable_r <= 'd3;
+ else
+ ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r1[chip_cnt_r];
+ end
+ else begin
+ if (init_state_r1 == INIT_PRECHARGE && init_done_r)
+ ddr_cs_disable_r <= 'd3;
+ else
+ ddr_cs_disable_r[chip_cnt_r] <= ~ddr_cs_n_r[chip_cnt_r];
+ end
+ end
+ end
+ end
+
+
+ assign phy_init_addr = ddr_addr_r;
+ assign phy_init_ba = ddr_ba_r;
+ assign phy_init_cas_n = ddr_cas_n_r;
+ assign phy_init_cke = ddr_cke_r;
+ assign phy_init_ras_n = ddr_ras_n_r;
+ assign phy_init_we_n = ddr_we_n_r;
+ assign phy_init_cs_n = (TWO_T_TIME_EN) ?
+ ddr_cs_n_r1 | ddr_cs_disable_r
+ : ddr_cs_n_r| ddr_cs_disable_r;
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_io.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_io.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_io.v (revision 3)
@@ -0,0 +1,353 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_phy_io.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module instantiates calibration logic, data, data strobe and the
+// data mask iobs.
+//Reference:
+//Revision History:
+// Rev 1.1 - DM_IOB instance made based on USE_DM_PORT value . PK. 25/6/08
+// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
+// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_io #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter CLK_WIDTH = 1,
+ parameter USE_DM_PORT = 1,
+ parameter DM_WIDTH = 9,
+ parameter DQ_WIDTH = 72,
+ parameter DQ_BITS = 7,
+ parameter DQ_PER_DQS = 8,
+ parameter DQS_BITS = 4,
+ parameter DQS_WIDTH = 9,
+ parameter HIGH_PERFORMANCE_MODE = "TRUE",
+ parameter IODELAY_GRP = "IODELAY_MIG",
+ parameter ODT_WIDTH = 1,
+ parameter ADDITIVE_LAT = 0,
+ parameter CAS_LAT = 5,
+ parameter REG_ENABLE = 1,
+ parameter CLK_PERIOD = 3000,
+ parameter DDR_TYPE = 1,
+ parameter SIM_ONLY = 0,
+ parameter DEBUG_EN = 0,
+ parameter FPGA_SPEED_GRADE = 2
+ )
+ (
+ input clk0,
+ input clk90,
+ input clkdiv0,
+ input rst0,
+ input rst90,
+ input rstdiv0,
+ input dm_ce,
+ input [1:0] dq_oe_n,
+ input dqs_oe_n,
+ input dqs_rst_n,
+ input [3:0] calib_start,
+ input ctrl_rden,
+ input phy_init_rden,
+ input calib_ref_done,
+ output [3:0] calib_done,
+ output calib_ref_req,
+ output [DQS_WIDTH-1:0] calib_rden,
+ output [DQS_WIDTH-1:0] calib_rden_sel,
+ input [DQ_WIDTH-1:0] wr_data_rise,
+ input [DQ_WIDTH-1:0] wr_data_fall,
+ input [(DQ_WIDTH/8)-1:0] mask_data_rise,
+ input [(DQ_WIDTH/8)-1:0] mask_data_fall,
+ output [(DQ_WIDTH)-1:0] rd_data_rise,
+ output [(DQ_WIDTH)-1:0] rd_data_fall,
+ output [CLK_WIDTH-1:0] ddr_ck,
+ output [CLK_WIDTH-1:0] ddr_ck_n,
+ output [DM_WIDTH-1:0] ddr_dm,
+ inout [DQS_WIDTH-1:0] ddr_dqs,
+ inout [DQS_WIDTH-1:0] ddr_dqs_n,
+ inout [DQ_WIDTH-1:0] ddr_dq,
+ // Debug signals (optional use)
+ input dbg_idel_up_all,
+ input dbg_idel_down_all,
+ input dbg_idel_up_dq,
+ input dbg_idel_down_dq,
+ input dbg_idel_up_dqs,
+ input dbg_idel_down_dqs,
+ input dbg_idel_up_gate,
+ input dbg_idel_down_gate,
+ input [DQ_BITS-1:0] dbg_sel_idel_dq,
+ input dbg_sel_all_idel_dq,
+ input [DQS_BITS:0] dbg_sel_idel_dqs,
+ input dbg_sel_all_idel_dqs,
+ input [DQS_BITS:0] dbg_sel_idel_gate,
+ input dbg_sel_all_idel_gate,
+ output [3:0] dbg_calib_done,
+ output [3:0] dbg_calib_err,
+ output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
+ output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
+ );
+
+ // ratio of # of physical DM outputs to bytes in data bus
+ // may be different - e.g. if using x4 components
+ localparam DM_TO_BYTE_RATIO = DM_WIDTH / (DQ_WIDTH/8);
+
+ wire [CLK_WIDTH-1:0] ddr_ck_q;
+ wire [DQS_WIDTH-1:0] delayed_dqs;
+ wire [DQ_WIDTH-1:0] dlyce_dq;
+ wire [DQS_WIDTH-1:0] dlyce_dqs;
+ wire [DQS_WIDTH-1:0] dlyce_gate;
+ wire [DQ_WIDTH-1:0] dlyinc_dq;
+ wire [DQS_WIDTH-1:0] dlyinc_dqs;
+ wire [DQS_WIDTH-1:0] dlyinc_gate;
+ wire dlyrst_dq;
+ wire dlyrst_dqs;
+ wire [DQS_WIDTH-1:0] dlyrst_gate;
+ wire [DQS_WIDTH-1:0] dq_ce;
+ (* KEEP = "TRUE" *) wire [DQS_WIDTH-1:0] en_dqs /* synthesis syn_keep = 1 */;
+ wire [DQS_WIDTH-1:0] rd_data_sel;
+
+ //***************************************************************************
+
+ ddr2_phy_calib #
+ (
+ .DQ_WIDTH (DQ_WIDTH),
+ .DQ_BITS (DQ_BITS),
+ .DQ_PER_DQS (DQ_PER_DQS),
+ .DQS_BITS (DQS_BITS),
+ .DQS_WIDTH (DQS_WIDTH),
+ .ADDITIVE_LAT (ADDITIVE_LAT),
+ .CAS_LAT (CAS_LAT),
+ .REG_ENABLE (REG_ENABLE),
+ .CLK_PERIOD (CLK_PERIOD),
+ .SIM_ONLY (SIM_ONLY),
+ .DEBUG_EN (DEBUG_EN)
+ )
+ u_phy_calib
+ (
+ .clk (clk0),
+ .clkdiv (clkdiv0),
+ .rstdiv (rstdiv0),
+ .calib_start (calib_start),
+ .ctrl_rden (ctrl_rden),
+ .phy_init_rden (phy_init_rden),
+ .rd_data_rise (rd_data_rise),
+ .rd_data_fall (rd_data_fall),
+ .calib_ref_done (calib_ref_done),
+ .calib_done (calib_done),
+ .calib_ref_req (calib_ref_req),
+ .calib_rden (calib_rden),
+ .calib_rden_sel (calib_rden_sel),
+ .dlyrst_dq (dlyrst_dq),
+ .dlyce_dq (dlyce_dq),
+ .dlyinc_dq (dlyinc_dq),
+ .dlyrst_dqs (dlyrst_dqs),
+ .dlyce_dqs (dlyce_dqs),
+ .dlyinc_dqs (dlyinc_dqs),
+ .dlyrst_gate (dlyrst_gate),
+ .dlyce_gate (dlyce_gate),
+ .dlyinc_gate (dlyinc_gate),
+ .en_dqs (en_dqs),
+ .rd_data_sel (rd_data_sel),
+ .dbg_idel_up_all (dbg_idel_up_all),
+ .dbg_idel_down_all (dbg_idel_down_all),
+ .dbg_idel_up_dq (dbg_idel_up_dq),
+ .dbg_idel_down_dq (dbg_idel_down_dq),
+ .dbg_idel_up_dqs (dbg_idel_up_dqs),
+ .dbg_idel_down_dqs (dbg_idel_down_dqs),
+ .dbg_idel_up_gate (dbg_idel_up_gate),
+ .dbg_idel_down_gate (dbg_idel_down_gate),
+ .dbg_sel_idel_dq (dbg_sel_idel_dq),
+ .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
+ .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
+ .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
+ .dbg_sel_idel_gate (dbg_sel_idel_gate),
+ .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate),
+ .dbg_calib_done (dbg_calib_done),
+ .dbg_calib_err (dbg_calib_err),
+ .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
+ .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
+ .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
+ .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
+ .dbg_calib_rden_dly (dbg_calib_rden_dly),
+ .dbg_calib_gate_dly (dbg_calib_gate_dly)
+ );
+
+ //***************************************************************************
+ // Memory clock generation
+ //***************************************************************************
+
+ genvar ck_i;
+ generate
+ for(ck_i = 0; ck_i < CLK_WIDTH; ck_i = ck_i+1) begin: gen_ck
+ ODDR #
+ (
+ .SRTYPE ("SYNC"),
+ .DDR_CLK_EDGE ("OPPOSITE_EDGE")
+ )
+ u_oddr_ck_i
+ (
+ .Q (ddr_ck_q[ck_i]),
+ .C (clk0),
+ .CE (1'b1),
+ .D1 (1'b0),
+ .D2 (1'b1),
+ .R (1'b0),
+ .S (1'b0)
+ );
+ // Can insert ODELAY here if required
+ OBUFDS u_obuf_ck_i
+ (
+ .I (ddr_ck_q[ck_i]),
+ .O (ddr_ck[ck_i]),
+ .OB (ddr_ck_n[ck_i])
+ );
+ end
+ endgenerate
+
+ //***************************************************************************
+ // DQS instances
+ //***************************************************************************
+
+ genvar dqs_i;
+ generate
+ for(dqs_i = 0; dqs_i < DQS_WIDTH; dqs_i = dqs_i+1) begin: gen_dqs
+ ddr2_phy_dqs_iob #
+ (
+ .DDR_TYPE (DDR_TYPE),
+ .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+ .IODELAY_GRP (IODELAY_GRP)
+ )
+ u_iob_dqs
+ (
+ .clk0 (clk0),
+ .clkdiv0 (clkdiv0),
+ .rst0 (rst0),
+ .dlyinc_dqs (dlyinc_dqs[dqs_i]),
+ .dlyce_dqs (dlyce_dqs[dqs_i]),
+ .dlyrst_dqs (dlyrst_dqs),
+ .dlyinc_gate (dlyinc_gate[dqs_i]),
+ .dlyce_gate (dlyce_gate[dqs_i]),
+ .dlyrst_gate (dlyrst_gate[dqs_i]),
+ .dqs_oe_n (dqs_oe_n),
+ .dqs_rst_n (dqs_rst_n),
+ .en_dqs (en_dqs[dqs_i]),
+ .ddr_dqs (ddr_dqs[dqs_i]),
+ .ddr_dqs_n (ddr_dqs_n[dqs_i]),
+ .dq_ce (dq_ce[dqs_i]),
+ .delayed_dqs (delayed_dqs[dqs_i])
+ );
+ end
+ endgenerate
+
+ //***************************************************************************
+ // DM instances
+ //***************************************************************************
+
+ genvar dm_i;
+ generate
+ if (USE_DM_PORT) begin: gen_dm_inst
+ for(dm_i = 0; dm_i < DM_WIDTH; dm_i = dm_i+1) begin: gen_dm
+ ddr2_phy_dm_iob u_iob_dm
+ (
+ .clk90 (clk90),
+ .dm_ce (dm_ce),
+ .mask_data_rise (mask_data_rise[dm_i/DM_TO_BYTE_RATIO]),
+ .mask_data_fall (mask_data_fall[dm_i/DM_TO_BYTE_RATIO]),
+ .ddr_dm (ddr_dm[dm_i])
+ );
+ end
+ end
+ endgenerate
+
+ //***************************************************************************
+ // DQ IOB instances
+ //***************************************************************************
+
+ genvar dq_i;
+ generate
+ for(dq_i = 0; dq_i < DQ_WIDTH; dq_i = dq_i+1) begin: gen_dq
+ ddr2_phy_dq_iob #
+ (
+ .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+ .IODELAY_GRP (IODELAY_GRP),
+ .FPGA_SPEED_GRADE (FPGA_SPEED_GRADE)
+ )
+ u_iob_dq
+ (
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .clkdiv0 (clkdiv0),
+ .rst90 (rst90),
+ .dlyinc (dlyinc_dq[dq_i]),
+ .dlyce (dlyce_dq[dq_i]),
+ .dlyrst (dlyrst_dq),
+ .dq_oe_n (dq_oe_n),
+ .dqs (delayed_dqs[dq_i/DQ_PER_DQS]),
+ .ce (dq_ce[dq_i/DQ_PER_DQS]),
+ .rd_data_sel (rd_data_sel[dq_i/DQ_PER_DQS]),
+ .wr_data_rise (wr_data_rise[dq_i]),
+ .wr_data_fall (wr_data_fall[dq_i]),
+ .rd_data_rise (rd_data_rise[dq_i]),
+ .rd_data_fall (rd_data_fall[dq_i]),
+ .ddr_dq (ddr_dq[dq_i])
+ );
+ end
+ endgenerate
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/MEMCtrl.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/MEMCtrl.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/MEMCtrl.v (revision 3)
@@ -0,0 +1,605 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: MEMCtrl.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// Top-level module. Simple model for what the user might use
+// Typically, the user will only instantiate MEM_INTERFACE_TOP in their
+// code, and generate all backend logic (test bench) and all the other infrastructure logic
+// separately.
+// In addition to the memory controller, the module instantiates:
+// 1. Reset logic based on user clocks
+// 2. IDELAY control block
+//Reference:
+//Revision History:
+// Rev 1.1 - Parameter USE_DM_PORT added. PK. 6/25/08
+// Rev 1.2 - Parameter HIGH_PERFORMANCE_MODE added. PK. 7/10/08
+// Rev 1.3 - Parameter IODELAY_GRP added. PK. 11/27/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+(* X_CORE_INFO = "mig_v3_61_ddr2_v5, Coregen 12.4" , CORE_GENERATION_INFO = "ddr2_v5,mig_v3_61,{component_name=MEMCtrl, BANK_WIDTH=2, CKE_WIDTH=1, CLK_WIDTH=2, COL_WIDTH=10, CS_NUM=1, CS_WIDTH=1, DM_WIDTH=8, DQ_WIDTH=64, DQ_PER_DQS=8, DQS_WIDTH=8, ODT_WIDTH=1, ROW_WIDTH=13, ADDITIVE_LAT=0, BURST_LEN=4, BURST_TYPE=0, CAS_LAT=3, ECC_ENABLE=0, MULTI_BANK_EN=1, TWO_T_TIME_EN=1, ODT_TYPE=1, REDUCE_DRV=0, REG_ENABLE=0, TREFI_NS=7800, TRAS=40000, TRCD=15000, TRFC=105000, TRP=15000, TRTP=7500, TWR=15000, TWTR=7500, CLK_PERIOD=8000, RST_ACT_LOW=1, INTERFACE_TYPE=DDR2_SDRAM, LANGUAGE=Verilog, SYNTHESIS_TOOL=ISE, NO_OF_CONTROLLERS=1}" *)
+module MEMCtrl #
+ (
+ parameter BANK_WIDTH = 2,
+ // # of memory bank addr bits.
+ parameter CKE_WIDTH = 1,
+ // # of memory clock enable outputs.
+ parameter CLK_WIDTH = 2,
+ // # of clock outputs.
+ parameter COL_WIDTH = 10,
+ // # of memory column bits.
+ parameter CS_NUM = 1,
+ // # of separate memory chip selects.
+ parameter CS_WIDTH = 1,
+ // # of total memory chip selects.
+ parameter CS_BITS = 0,
+ // set to log2(CS_NUM) (rounded up).
+ parameter DM_WIDTH = 8,
+ // # of data mask bits.
+ parameter DQ_WIDTH = 64,
+ // # of data width.
+ parameter DQ_PER_DQS = 8,
+ // # of DQ data bits per strobe.
+ parameter DQS_WIDTH = 8,
+ // # of DQS strobes.
+ parameter DQ_BITS = 6,
+ // set to log2(DQS_WIDTH*DQ_PER_DQS).
+ parameter DQS_BITS = 3,
+ // set to log2(DQS_WIDTH).
+ parameter ODT_WIDTH = 1,
+ // # of memory on-die term enables.
+ parameter ROW_WIDTH = 13,
+ // # of memory row and # of addr bits.
+ parameter ADDITIVE_LAT = 0,
+ // additive write latency.
+ parameter BURST_LEN = 4,
+ // burst length (in double words).
+ parameter BURST_TYPE = 0,
+ // burst type (=0 seq; =1 interleaved).
+ parameter CAS_LAT = 3,
+ // CAS latency.
+ parameter ECC_ENABLE = 0,
+ // enable ECC (=1 enable).
+ parameter APPDATA_WIDTH = 128,
+ // # of usr read/write data bus bits.
+ parameter MULTI_BANK_EN = 1,
+ // Keeps multiple banks open. (= 1 enable).
+ parameter TWO_T_TIME_EN = 1,
+ // 2t timing for unbuffered dimms.
+ parameter ODT_TYPE = 1,
+ // ODT (=0(none),=1(75),=2(150),=3(50)).
+ parameter REDUCE_DRV = 0,
+ // reduced strength mem I/O (=1 yes).
+ parameter REG_ENABLE = 0,
+ // registered addr/ctrl (=1 yes).
+ parameter TREFI_NS = 7800,
+ // auto refresh interval (ns).
+ parameter TRAS = 40000,
+ // active->precharge delay.
+ parameter TRCD = 15000,
+ // active->read/write delay.
+ parameter TRFC = 105000,
+ // refresh->refresh, refresh->active delay.
+ parameter TRP = 15000,
+ // precharge->command delay.
+ parameter TRTP = 7500,
+ // read->precharge delay.
+ parameter TWR = 15000,
+ // used to determine write->precharge.
+ parameter TWTR = 7500,
+ // write->read delay.
+ parameter HIGH_PERFORMANCE_MODE = "TRUE",
+ // # = TRUE, the IODELAY performance mode is set
+ // to high.
+ // # = FALSE, the IODELAY performance mode is set
+ // to low.
+ parameter SIM_ONLY = 0,
+ // = 1 to skip SDRAM power up delay.
+ parameter DEBUG_EN = 0,
+ // Enable debug signals/controls.
+ // When this parameter is changed from 0 to 1,
+ // make sure to uncomment the coregen commands
+ // in ise_flow.bat or create_ise.bat files in
+ // par folder.
+ parameter CLK_PERIOD = 8000,
+ // Core/Memory clock period (in ps).
+ parameter RST_ACT_LOW = 1
+ // =1 for active low reset, =0 for active high.
+ )
+ (
+ inout [DQ_WIDTH-1:0] ddr2_dq,
+ output [ROW_WIDTH-1:0] ddr2_a,
+ output [BANK_WIDTH-1:0] ddr2_ba,
+ output ddr2_ras_n,
+ output ddr2_cas_n,
+ output ddr2_we_n,
+ output [CS_WIDTH-1:0] ddr2_cs_n,
+ output [ODT_WIDTH-1:0] ddr2_odt,
+ output [CKE_WIDTH-1:0] ddr2_cke,
+ output [DM_WIDTH-1:0] ddr2_dm,
+ input sys_rst_n,
+ output phy_init_done,
+ input locked,
+ output rst0_tb,
+ input clk0,
+ output clk0_tb,
+ input clk90,
+ input clkdiv0,
+ input clk200,
+ output app_wdf_afull,
+ output app_af_afull,
+ output rd_data_valid,
+ input app_wdf_wren,
+ input app_af_wren,
+ input [30:0] app_af_addr,
+ input [2:0] app_af_cmd,
+ output [(APPDATA_WIDTH)-1:0] rd_data_fifo_out,
+ input [(APPDATA_WIDTH)-1:0] app_wdf_data,
+ input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
+ inout [DQS_WIDTH-1:0] ddr2_dqs,
+ inout [DQS_WIDTH-1:0] ddr2_dqs_n,
+ output [CLK_WIDTH-1:0] ddr2_ck,
+ output [CLK_WIDTH-1:0] ddr2_ck_n//,
+ //ADAUGAT PT LEDURI
+ //output error_o, error_cmp_o
+ );
+
+ //***************************************************************************
+ // IODELAY Group Name: Replication and placement of IDELAYCTRLs will be
+ // handled automatically by software tools if IDELAYCTRLs have same refclk,
+ // reset and rdy nets. Designs with a unique RESET will commonly create a
+ // unique RDY. Constraint IODELAY_GROUP is associated to a set of IODELAYs
+ // with an IDELAYCTRL. The parameter IODELAY_GRP value can be any string.
+ //***************************************************************************
+
+ localparam IODELAY_GRP = "IODELAY_MIG";
+
+
+
+
+
+ wire rst0;
+ wire rst90;
+ wire rstdiv0;
+ wire rst200;
+ wire idelay_ctrl_rdy;
+
+ wire error;
+ wire error_cmp;
+ wire [35:0] control;
+ wire [71:0] data;
+ wire [7:0] trig0;
+
+ //Debug signals
+
+
+ wire [3:0] dbg_calib_done;
+ wire [3:0] dbg_calib_err;
+ wire [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt;
+ wire [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt;
+ wire [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt;
+ wire [DQS_WIDTH-1:0] dbg_calib_rd_data_sel;
+ wire [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly;
+ wire [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly;
+ wire dbg_idel_up_all;
+ wire dbg_idel_down_all;
+ wire dbg_idel_up_dq;
+ wire dbg_idel_down_dq;
+ wire dbg_idel_up_dqs;
+ wire dbg_idel_down_dqs;
+ wire dbg_idel_up_gate;
+ wire dbg_idel_down_gate;
+ wire [DQ_BITS-1:0] dbg_sel_idel_dq;
+ wire dbg_sel_all_idel_dq;
+ wire [DQS_BITS:0] dbg_sel_idel_dqs;
+ wire dbg_sel_all_idel_dqs;
+ wire [DQS_BITS:0] dbg_sel_idel_gate;
+ wire dbg_sel_all_idel_gate;
+
+
+ // Debug signals (optional use)
+
+ //***********************************
+ // PHY Debug Port demo
+ //***********************************
+ wire [35:0] cs_control0;
+ wire [35:0] cs_control1;
+ wire [35:0] cs_control2;
+ wire [35:0] cs_control3;
+ wire [191:0] vio0_in;
+ wire [95:0] vio1_in;
+ wire [99:0] vio2_in;
+ wire [31:0] vio3_out;
+
+
+
+
+ //***************************************************************************
+
+ assign rst0_tb = rst0;
+ assign clk0_tb = clk0;
+
+
+ddr2_idelay_ctrl #
+ (
+ .IODELAY_GRP (IODELAY_GRP)
+ )
+ u_ddr2_idelay_ctrl
+ (
+ .rst200 (rst200),
+ .clk200 (clk200),
+ .idelay_ctrl_rdy (idelay_ctrl_rdy)
+ );
+
+ ddr2_infrastructure #
+ (
+ .RST_ACT_LOW (RST_ACT_LOW)
+ )
+u_ddr2_infrastructure
+ (
+ .sys_rst_n (sys_rst_n),
+ .locked (locked),
+ .rst0 (rst0),
+ .rst90 (rst90),
+ .rstdiv0 (rstdiv0),
+ .rst200 (rst200),
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .clkdiv0 (clkdiv0),
+ .clk200 (clk200),
+ .idelay_ctrl_rdy (idelay_ctrl_rdy)
+ );
+
+ ddr2_top #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .CKE_WIDTH (CKE_WIDTH),
+ .CLK_WIDTH (CLK_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .CS_NUM (CS_NUM),
+ .CS_WIDTH (CS_WIDTH),
+ .CS_BITS (CS_BITS),
+ .DM_WIDTH (DM_WIDTH),
+ .DQ_WIDTH (DQ_WIDTH),
+ .DQ_PER_DQS (DQ_PER_DQS),
+ .DQS_WIDTH (DQS_WIDTH),
+ .DQ_BITS (DQ_BITS),
+ .DQS_BITS (DQS_BITS),
+ .ODT_WIDTH (ODT_WIDTH),
+ .ROW_WIDTH (ROW_WIDTH),
+ .ADDITIVE_LAT (ADDITIVE_LAT),
+ .BURST_LEN (BURST_LEN),
+ .BURST_TYPE (BURST_TYPE),
+ .CAS_LAT (CAS_LAT),
+ .ECC_ENABLE (ECC_ENABLE),
+ .APPDATA_WIDTH (APPDATA_WIDTH),
+ .MULTI_BANK_EN (MULTI_BANK_EN),
+ .TWO_T_TIME_EN (TWO_T_TIME_EN),
+ .ODT_TYPE (ODT_TYPE),
+ .REDUCE_DRV (REDUCE_DRV),
+ .REG_ENABLE (REG_ENABLE),
+ .TREFI_NS (TREFI_NS),
+ .TRAS (TRAS),
+ .TRCD (TRCD),
+ .TRFC (TRFC),
+ .TRP (TRP),
+ .TRTP (TRTP),
+ .TWR (TWR),
+ .TWTR (TWTR),
+ .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
+ .IODELAY_GRP (IODELAY_GRP),
+ .SIM_ONLY (SIM_ONLY),
+ .DEBUG_EN (DEBUG_EN),
+ .FPGA_SPEED_GRADE (3),
+ .USE_DM_PORT (1),
+ .CLK_PERIOD (CLK_PERIOD)
+ )
+u_ddr2_top_0
+(
+ .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),
+ .phy_init_done (phy_init_done),
+ .rst0 (rst0),
+ .rst90 (rst90),
+ .rstdiv0 (rstdiv0),
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .clkdiv0 (clkdiv0),
+ .app_wdf_afull (app_wdf_afull),
+ .app_af_afull (app_af_afull),
+ .rd_data_valid (rd_data_valid),
+ .app_wdf_wren (app_wdf_wren),
+ .app_af_wren (app_af_wren),
+ .app_af_addr (app_af_addr),
+ .app_af_cmd (app_af_cmd),
+ .rd_data_fifo_out (rd_data_fifo_out),
+ .app_wdf_data (app_wdf_data),
+ .app_wdf_mask_data (app_wdf_mask_data),
+ .ddr2_dqs (ddr2_dqs),
+ .ddr2_dqs_n (ddr2_dqs_n),
+ .ddr2_ck (ddr2_ck),
+ .rd_ecc_error (),
+ .ddr2_ck_n (ddr2_ck_n),
+
+ .dbg_calib_done (dbg_calib_done),
+ .dbg_calib_err (dbg_calib_err),
+ .dbg_calib_dq_tap_cnt (dbg_calib_dq_tap_cnt),
+ .dbg_calib_dqs_tap_cnt (dbg_calib_dqs_tap_cnt),
+ .dbg_calib_gate_tap_cnt (dbg_calib_gate_tap_cnt),
+ .dbg_calib_rd_data_sel (dbg_calib_rd_data_sel),
+ .dbg_calib_rden_dly (dbg_calib_rden_dly),
+ .dbg_calib_gate_dly (dbg_calib_gate_dly),
+ .dbg_idel_up_all (dbg_idel_up_all),
+ .dbg_idel_down_all (dbg_idel_down_all),
+ .dbg_idel_up_dq (dbg_idel_up_dq),
+ .dbg_idel_down_dq (dbg_idel_down_dq),
+ .dbg_idel_up_dqs (dbg_idel_up_dqs),
+ .dbg_idel_down_dqs (dbg_idel_down_dqs),
+ .dbg_idel_up_gate (dbg_idel_up_gate),
+ .dbg_idel_down_gate (dbg_idel_down_gate),
+ .dbg_sel_idel_dq (dbg_sel_idel_dq),
+ .dbg_sel_all_idel_dq (dbg_sel_all_idel_dq),
+ .dbg_sel_idel_dqs (dbg_sel_idel_dqs),
+ .dbg_sel_all_idel_dqs (dbg_sel_all_idel_dqs),
+ .dbg_sel_idel_gate (dbg_sel_idel_gate),
+ .dbg_sel_all_idel_gate (dbg_sel_all_idel_gate)
+ );
+
+
+ //*****************************************************************
+ // Hooks to prevent sim/syn compilation errors (mainly for VHDL - but
+ // keep it also in Verilog version of code) w/ floating inputs if
+ // DEBUG_EN = 0.
+ //*****************************************************************
+
+ generate
+ if (DEBUG_EN == 0) begin: gen_dbg_tie_off
+ assign dbg_idel_up_all = 'b0;
+ assign dbg_idel_down_all = 'b0;
+ assign dbg_idel_up_dq = 'b0;
+ assign dbg_idel_down_dq = 'b0;
+ assign dbg_idel_up_dqs = 'b0;
+ assign dbg_idel_down_dqs = 'b0;
+ assign dbg_idel_up_gate = 'b0;
+ assign dbg_idel_down_gate = 'b0;
+ assign dbg_sel_idel_dq = 'b0;
+ assign dbg_sel_all_idel_dq = 'b0;
+ assign dbg_sel_idel_dqs = 'b0;
+ assign dbg_sel_all_idel_dqs = 'b0;
+ assign dbg_sel_idel_gate = 'b0;
+ assign dbg_sel_all_idel_gate = 'b0;
+ end else begin: gen_dbg_enable
+
+ //*****************************************************************
+ // PHY Debug Port example - see MIG User's Guide, XAPP858 or
+ // Answer Record 29443
+ // This logic supports up to 32 DQ and 8 DQS I/O
+ // NOTES:
+ // 1. PHY Debug Port demo connects to 4 VIO modules:
+ // - 3 VIO modules with only asynchronous inputs
+ // * Monitor IDELAY taps for DQ, DQS, DQS Gate
+ // * Calibration status
+ // - 1 VIO module with synchronous outputs
+ // * Allow dynamic adjustment o f IDELAY taps
+ // 2. User may need to modify this code to incorporate other
+ // chipscope-related modules in their larger design (e.g.
+ // if they have other ILA/VIO modules, they will need to
+ // for example instantiate a larger ICON module). In addition
+ // user may want to instantiate more VIO modules to control
+ // IDELAY for more DQ, DQS than is shown here
+ //*****************************************************************
+
+ icon4 u_icon
+ (
+ .control0 (cs_control0),
+ .control1 (cs_control1),
+ .control2 (cs_control2),
+ .control3 (cs_control3)
+ );
+
+ //*****************************************************************
+ // VIO ASYNC input: Display current IDELAY setting for up to 32
+ // DQ taps (32x6) = 192
+ //*****************************************************************
+
+ vio_async_in192 u_vio0
+ (
+ .control (cs_control0),
+ .async_in (vio0_in)
+ );
+
+ //*****************************************************************
+ // VIO ASYNC input: Display current IDELAY setting for up to 8 DQS
+ // and DQS Gate taps (8x6x2) = 96
+ //*****************************************************************
+
+ vio_async_in96 u_vio1
+ (
+ .control (cs_control1),
+ .async_in (vio1_in)
+ );
+
+ //*****************************************************************
+ // VIO ASYNC input: Display other calibration results
+ //*****************************************************************
+
+ vio_async_in100 u_vio2
+ (
+ .control (cs_control2),
+ .async_in (vio2_in)
+ );
+
+ //*****************************************************************
+ // VIO SYNC output: Dynamically change IDELAY taps
+ //*****************************************************************
+
+ vio_sync_out32 u_vio3
+ (
+ .control (cs_control3),
+ .clk (clkdiv0),
+ .sync_out (vio3_out)
+ );
+
+ //*****************************************************************
+ // Bit assignments:
+ // NOTE: Not all VIO, ILA inputs/outputs may be used - these will
+ // be dependent on the user's particular bit width
+ //*****************************************************************
+
+ if (DQ_WIDTH <= 32) begin: gen_dq_le_32
+ assign vio0_in[(6*DQ_WIDTH)-1:0]
+ = dbg_calib_dq_tap_cnt[(6*DQ_WIDTH)-1:0];
+ end else begin: gen_dq_gt_32
+ assign vio0_in = dbg_calib_dq_tap_cnt[191:0];
+ end
+
+ if (DQS_WIDTH <= 8) begin: gen_dqs_le_8
+ assign vio1_in[(6*DQS_WIDTH)-1:0]
+ = dbg_calib_dqs_tap_cnt[(6*DQS_WIDTH)-1:0];
+ assign vio1_in[(12*DQS_WIDTH)-1:(6*DQS_WIDTH)]
+ = dbg_calib_gate_tap_cnt[(6*DQS_WIDTH)-1:0];
+ end else begin: gen_dqs_gt_32
+ assign vio1_in[47:0] = dbg_calib_dqs_tap_cnt[47:0];
+ assign vio1_in[95:48] = dbg_calib_gate_tap_cnt[47:0];
+ end
+
+//dbg_calib_rd_data_sel
+
+ if (DQS_WIDTH <= 8) begin: gen_rdsel_le_8
+ assign vio2_in[(DQS_WIDTH)+7:8]
+ = dbg_calib_rd_data_sel[(DQS_WIDTH)-1:0];
+ end else begin: gen_rdsel_gt_32
+ assign vio2_in[15:8]
+ = dbg_calib_rd_data_sel[7:0];
+ end
+
+//dbg_calib_rden_dly
+
+ if (DQS_WIDTH <= 8) begin: gen_calrd_le_8
+ assign vio2_in[(5*DQS_WIDTH)+19:20]
+ = dbg_calib_rden_dly[(5*DQS_WIDTH)-1:0];
+ end else begin: gen_calrd_gt_32
+ assign vio2_in[59:20]
+ = dbg_calib_rden_dly[39:0];
+ end
+
+//dbg_calib_gate_dly
+
+ if (DQS_WIDTH <= 8) begin: gen_calgt_le_8
+ assign vio2_in[(5*DQS_WIDTH)+59:60]
+ = dbg_calib_gate_dly[(5*DQS_WIDTH)-1:0];
+ end else begin: gen_calgt_gt_32
+ assign vio2_in[99:60]
+ = dbg_calib_gate_dly[39:0];
+ end
+
+//dbg_sel_idel_dq
+
+ if (DQ_BITS <= 5) begin: gen_selid_le_5
+ assign dbg_sel_idel_dq[DQ_BITS-1:0]
+ = vio3_out[DQ_BITS+7:8];
+ end else begin: gen_selid_gt_32
+ assign dbg_sel_idel_dq[4:0]
+ = vio3_out[12:8];
+ end
+
+//dbg_sel_idel_dqs
+
+ if (DQS_BITS <= 3) begin: gen_seldqs_le_3
+ assign dbg_sel_idel_dqs[DQS_BITS:0]
+ = vio3_out[(DQS_BITS+16):16];
+ end else begin: gen_seldqs_gt_32
+ assign dbg_sel_idel_dqs[3:0]
+ = vio3_out[19:16];
+ end
+
+//dbg_sel_idel_gate
+
+ if (DQS_BITS <= 3) begin: gen_gtdqs_le_3
+ assign dbg_sel_idel_gate[DQS_BITS:0]
+ = vio3_out[(DQS_BITS+21):21];
+ end else begin: gen_gtdqs_gt_32
+ assign dbg_sel_idel_gate[3:0]
+ = vio3_out[24:21];
+ end
+
+
+ assign vio2_in[3:0] = dbg_calib_done;
+ assign vio2_in[7:4] = dbg_calib_err;
+
+ assign dbg_idel_up_all = vio3_out[0];
+ assign dbg_idel_down_all = vio3_out[1];
+ assign dbg_idel_up_dq = vio3_out[2];
+ assign dbg_idel_down_dq = vio3_out[3];
+ assign dbg_idel_up_dqs = vio3_out[4];
+ assign dbg_idel_down_dqs = vio3_out[5];
+ assign dbg_idel_up_gate = vio3_out[6];
+ assign dbg_idel_down_gate = vio3_out[7];
+ assign dbg_sel_all_idel_dq = vio3_out[15];
+ assign dbg_sel_all_idel_dqs = vio3_out[20];
+ assign dbg_sel_all_idel_gate = vio3_out[25];
+ end
+ endgenerate
+
+
+endmodule
+
+
+
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_ctl_io.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_ctl_io.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_ctl_io.v (revision 3)
@@ -0,0 +1,304 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_phy_ctl_io.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Thu Aug 24 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module puts the memory control signals like address, bank address,
+// row address strobe, column address strobe, write enable and clock enable
+// in the IOBs.
+//Reference:
+//Revision History:
+// Rev 1.1 - To fix CR 540201, S attribute is added for CS, CKE and ODT
+// module (FDCPE) instances. PK. 01/08/10
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_ctl_io #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter CKE_WIDTH = 1,
+ parameter COL_WIDTH = 10,
+ parameter CS_NUM = 1,
+ parameter TWO_T_TIME_EN = 0,
+ parameter CS_WIDTH = 1,
+ parameter ODT_WIDTH = 1,
+ parameter ROW_WIDTH = 14,
+ parameter DDR_TYPE = 1
+ )
+ (
+ input clk0,
+ input clk90,
+ input rst0,
+ input rst90,
+ input [ROW_WIDTH-1:0] ctrl_addr,
+ input [BANK_WIDTH-1:0] ctrl_ba,
+ input ctrl_ras_n,
+ input ctrl_cas_n,
+ input ctrl_we_n,
+ input [CS_NUM-1:0] ctrl_cs_n,
+ input [ROW_WIDTH-1:0] phy_init_addr,
+ input [BANK_WIDTH-1:0] phy_init_ba,
+ input phy_init_ras_n,
+ input phy_init_cas_n,
+ input phy_init_we_n,
+ input [CS_NUM-1:0] phy_init_cs_n,
+ input [CKE_WIDTH-1:0] phy_init_cke,
+ input phy_init_data_sel,
+ input [CS_NUM-1:0] odt,
+ output [ROW_WIDTH-1:0] ddr_addr,
+ output [BANK_WIDTH-1:0] ddr_ba,
+ output ddr_ras_n,
+ output ddr_cas_n,
+ output ddr_we_n,
+ output [CKE_WIDTH-1:0] ddr_cke,
+ output [CS_WIDTH-1:0] ddr_cs_n,
+ output [ODT_WIDTH-1:0] ddr_odt
+ );
+
+ reg [ROW_WIDTH-1:0] addr_mux;
+ reg [BANK_WIDTH-1:0] ba_mux;
+ reg cas_n_mux;
+ reg [CS_NUM-1:0] cs_n_mux;
+ reg ras_n_mux;
+ reg we_n_mux;
+
+
+
+ //***************************************************************************
+
+
+
+
+ // MUX to choose from either PHY or controller for SDRAM control
+
+ generate // in 2t timing mode the extra register stage cannot be used.
+ if(TWO_T_TIME_EN) begin // the control signals are asserted for two cycles
+ always @(*)begin
+ if (phy_init_data_sel) begin
+ addr_mux = ctrl_addr;
+ ba_mux = ctrl_ba;
+ cas_n_mux = ctrl_cas_n;
+ cs_n_mux = ctrl_cs_n;
+ ras_n_mux = ctrl_ras_n;
+ we_n_mux = ctrl_we_n;
+ end else begin
+ addr_mux = phy_init_addr;
+ ba_mux = phy_init_ba;
+ cas_n_mux = phy_init_cas_n;
+ cs_n_mux = phy_init_cs_n;
+ ras_n_mux = phy_init_ras_n;
+ we_n_mux = phy_init_we_n;
+ end
+ end
+ end else begin
+ always @(posedge clk0)begin // register the signals in non 2t mode
+ if (phy_init_data_sel) begin
+ addr_mux <= ctrl_addr;
+ ba_mux <= ctrl_ba;
+ cas_n_mux <= ctrl_cas_n;
+ cs_n_mux <= ctrl_cs_n;
+ ras_n_mux <= ctrl_ras_n;
+ we_n_mux <= ctrl_we_n;
+ end else begin
+ addr_mux <= phy_init_addr;
+ ba_mux <= phy_init_ba;
+ cas_n_mux <= phy_init_cas_n;
+ cs_n_mux <= phy_init_cs_n;
+ ras_n_mux <= phy_init_ras_n;
+ we_n_mux <= phy_init_we_n;
+ end
+ end
+ end
+ endgenerate
+
+ //***************************************************************************
+ // Output flop instantiation
+ // NOTE: Make sure all control/address flops are placed in IOBs
+ //***************************************************************************
+
+ // RAS: = 1 at reset
+ (* IOB = "FORCE" *) FDCPE u_ff_ras_n
+ (
+ .Q (ddr_ras_n),
+ .C (clk0),
+ .CE (1'b1),
+ .CLR (1'b0),
+ .D (ras_n_mux),
+ .PRE (rst0)
+ ) /* synthesis syn_useioff = 1 */;
+
+ // CAS: = 1 at reset
+ (* IOB = "FORCE" *) FDCPE u_ff_cas_n
+ (
+ .Q (ddr_cas_n),
+ .C (clk0),
+ .CE (1'b1),
+ .CLR (1'b0),
+ .D (cas_n_mux),
+ .PRE (rst0)
+ ) /* synthesis syn_useioff = 1 */;
+
+ // WE: = 1 at reset
+ (* IOB = "FORCE" *) FDCPE u_ff_we_n
+ (
+ .Q (ddr_we_n),
+ .C (clk0),
+ .CE (1'b1),
+ .CLR (1'b0),
+ .D (we_n_mux),
+ .PRE (rst0)
+ ) /* synthesis syn_useioff = 1 */;
+
+ // CKE: = 0 at reset
+ genvar cke_i;
+ generate
+ for (cke_i = 0; cke_i < CKE_WIDTH; cke_i = cke_i + 1) begin: gen_cke
+ (* IOB = "FORCE" *) (* S = "TRUE" *) FDCPE u_ff_cke
+ (
+ .Q (ddr_cke[cke_i]),
+ .C (clk0),
+ .CE (1'b1),
+ .CLR (rst0),
+ .D (phy_init_cke[cke_i]),
+ .PRE (1'b0)
+ ) /* synthesis syn_useioff = 1 */;
+ end
+ endgenerate
+
+ // chip select: = 1 at reset
+ // For unbuffered dimms the loading will be high. The chip select
+ // can be asserted early if the loading is very high. The
+ // code as is uses clock 0. If needed clock 270 can be used to
+ // toggle chip select 1/4 clock cycle early. The code has
+ // the clock 90 input for the early assertion of chip select.
+
+ genvar cs_i;
+ generate
+ for(cs_i = 0; cs_i < CS_WIDTH; cs_i = cs_i + 1) begin: gen_cs_n
+ if(TWO_T_TIME_EN) begin
+ (* IOB = "FORCE" *) (* S = "TRUE" *) FDCPE u_ff_cs_n
+ (
+ .Q (ddr_cs_n[cs_i]),
+ .C (clk0),
+ .CE (1'b1),
+ .CLR (1'b0),
+ .D (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
+ .PRE (rst0)
+ ) /* synthesis syn_useioff = 1 */;
+ end else begin // if (TWO_T_TIME_EN)
+ (* IOB = "FORCE" *) (* S = "TRUE" *) FDCPE u_ff_cs_n
+ (
+ .Q (ddr_cs_n[cs_i]),
+ .C (clk0),
+ .CE (1'b1),
+ .CLR (1'b0),
+ .D (cs_n_mux[(cs_i*CS_NUM)/CS_WIDTH]),
+ .PRE (rst0)
+ ) /* synthesis syn_useioff = 1 */;
+ end // else: !if(TWO_T_TIME_EN)
+ end
+ endgenerate
+
+ // address: = X at reset
+ genvar addr_i;
+ generate
+ for (addr_i = 0; addr_i < ROW_WIDTH; addr_i = addr_i + 1) begin: gen_addr
+ (* IOB = "FORCE" *) FDCPE u_ff_addr
+ (
+ .Q (ddr_addr[addr_i]),
+ .C (clk0),
+ .CE (1'b1),
+ .CLR (1'b0),
+ .D (addr_mux[addr_i]),
+ .PRE (1'b0)
+ ) /* synthesis syn_useioff = 1 */;
+ end
+ endgenerate
+
+ // bank address = X at reset
+ genvar ba_i;
+ generate
+ for (ba_i = 0; ba_i < BANK_WIDTH; ba_i = ba_i + 1) begin: gen_ba
+ (* IOB = "FORCE" *) FDCPE u_ff_ba
+ (
+ .Q (ddr_ba[ba_i]),
+ .C (clk0),
+ .CE (1'b1),
+ .CLR (1'b0),
+ .D (ba_mux[ba_i]),
+ .PRE (1'b0)
+ ) /* synthesis syn_useioff = 1 */;
+ end
+ endgenerate
+
+ // ODT control = 0 at reset
+ genvar odt_i;
+ generate
+ if (DDR_TYPE > 0) begin: gen_odt_ddr2
+ for (odt_i = 0; odt_i < ODT_WIDTH; odt_i = odt_i + 1) begin: gen_odt
+ (* IOB = "FORCE" *) (* S = "TRUE" *) FDCPE u_ff_odt
+ (
+ .Q (ddr_odt[odt_i]),
+ .C (clk0),
+ .CE (1'b1),
+ .CLR (rst0),
+ .D (odt[(odt_i*CS_NUM)/ODT_WIDTH]),
+ .PRE (1'b0)
+ ) /* synthesis syn_useioff = 1 */;
+ end
+ end
+ endgenerate
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_calib.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_calib.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_phy_calib.v (revision 3)
@@ -0,0 +1,2428 @@
+//*****************************************************************************
+// (c) Copyright 2006-2009 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.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_phy_calib.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Thu Aug 10 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module handles calibration after memory initialization.
+//Reference:
+//Revision History:
+// Rev 1.1 - Default statement is added for the CASE statement of
+// rdd_mux_sel logic. PK. 03/23/09
+// Rev 1.2 - Change training pattern detected for stage 3 calibration.
+// Use 2-bits per DQS group for stage 3 pattern detection.
+// RC. 09/21/09
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_phy_calib #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter DQ_WIDTH = 72,
+ parameter DQ_BITS = 7,
+ parameter DQ_PER_DQS = 8,
+ parameter DQS_BITS = 4,
+ parameter DQS_WIDTH = 9,
+ parameter ADDITIVE_LAT = 0,
+ parameter CAS_LAT = 5,
+ parameter REG_ENABLE = 1,
+ parameter CLK_PERIOD = 3000,
+ parameter SIM_ONLY = 0,
+ parameter DEBUG_EN = 0
+ )
+ (
+ input clk,
+ input clkdiv,
+ input rstdiv,
+ input [3:0] calib_start,
+ input ctrl_rden,
+ input phy_init_rden,
+ input [DQ_WIDTH-1:0] rd_data_rise,
+ input [DQ_WIDTH-1:0] rd_data_fall,
+ input calib_ref_done,
+ output reg [3:0] calib_done,
+ output reg calib_ref_req,
+ output [DQS_WIDTH-1:0] calib_rden,
+ output reg [DQS_WIDTH-1:0] calib_rden_sel,
+ output reg dlyrst_dq,
+ output reg [DQ_WIDTH-1:0] dlyce_dq,
+ output reg [DQ_WIDTH-1:0] dlyinc_dq,
+ output reg dlyrst_dqs,
+ output reg [DQS_WIDTH-1:0] dlyce_dqs,
+ output reg [DQS_WIDTH-1:0] dlyinc_dqs,
+ output reg [DQS_WIDTH-1:0] dlyrst_gate,
+ output reg [DQS_WIDTH-1:0] dlyce_gate,
+ output reg [DQS_WIDTH-1:0] dlyinc_gate,
+ //(* XIL_PAR_NO_REG_ORDER = "TRUE", XIL_PAR_PATH="Q->u_iodelay_dq_ce.DATAIN", syn_keep = "1", keep = "TRUE"*)
+ output [DQS_WIDTH-1:0] en_dqs,
+ output [DQS_WIDTH-1:0] rd_data_sel,
+ // Debug signals (optional use)
+ input dbg_idel_up_all,
+ input dbg_idel_down_all,
+ input dbg_idel_up_dq,
+ input dbg_idel_down_dq,
+ input dbg_idel_up_dqs,
+ input dbg_idel_down_dqs,
+ input dbg_idel_up_gate,
+ input dbg_idel_down_gate,
+ input [DQ_BITS-1:0] dbg_sel_idel_dq,
+ input dbg_sel_all_idel_dq,
+ input [DQS_BITS:0] dbg_sel_idel_dqs,
+ input dbg_sel_all_idel_dqs,
+ input [DQS_BITS:0] dbg_sel_idel_gate,
+ input dbg_sel_all_idel_gate,
+ output [3:0] dbg_calib_done,
+ output [3:0] dbg_calib_err,
+ output [(6*DQ_WIDTH)-1:0] dbg_calib_dq_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_dqs_tap_cnt,
+ output [(6*DQS_WIDTH)-1:0] dbg_calib_gate_tap_cnt,
+ output [DQS_WIDTH-1:0] dbg_calib_rd_data_sel,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_rden_dly,
+ output [(5*DQS_WIDTH)-1:0] dbg_calib_gate_dly
+ );
+
+ // minimum time (in IDELAY taps) for which capture data must be stable for
+ // algorithm to consider
+ localparam MIN_WIN_SIZE = 5;
+ // IDEL_SET_VAL = (# of cycles - 1) to wait after changing IDELAY value
+ // we only have to wait enough for input with new IDELAY value to
+ // propagate through pipeline stages.
+ localparam IDEL_SET_VAL = 3'b111;
+ // # of clock cycles to delay read enable to determine if read data pattern
+ // is correct for stage 3/4 (RDEN, DQS gate) calibration
+ localparam CALIB_RDEN_PIPE_LEN = 31;
+ // translate CAS latency into number of clock cycles for read valid delay
+ // determination. Really only needed for CL = 2.5 (set to 2)
+ localparam CAS_LAT_RDEN = (CAS_LAT == 25) ? 2 : CAS_LAT;
+ // an SRL32 is used to delay CTRL_RDEN to generate read valid signal. This
+ // is min possible value delay through SRL32 can be
+ localparam RDEN_BASE_DELAY = CAS_LAT_RDEN + ADDITIVE_LAT + REG_ENABLE;
+ // an SRL32 is used to delay the CTRL_RDEN from the read postamble DQS
+ // gate. This is min possible value the SRL32 delay can be:
+ // - Delay from end of deassertion of CTRL_RDEN to last falling edge of
+ // read burst = 3.5 (CTRL_RDEN -> CAS delay) + 3 (min CAS latency) = 6.5
+ // - Minimum time for DQS gate circuit to be generated:
+ // * 1 cyc to register CTRL_RDEN from controller
+ // * 1 cyc after RDEN_CTRL falling edge
+ // * 1 cyc min through SRL32
+ // * 1 cyc through SRL32 output flop
+ // * 0 (<1) cyc of synchronization to DQS domain via IDELAY
+ // * 1 cyc of delay through IDDR to generate CE to DQ IDDR's
+ // Total = 5 cyc < 6.5 cycles
+ // The total should be less than 5.5 cycles to account prop delays
+ // adding one cycle to the synchronization time via the IDELAY.
+ // NOTE: Value differs because of optional pipeline register added
+ // for case of RDEN_BASE_DELAY > 3 to improve timing
+ localparam GATE_BASE_DELAY = RDEN_BASE_DELAY - 3;
+ localparam GATE_BASE_INIT = (GATE_BASE_DELAY <= 1) ? 0 : GATE_BASE_DELAY;
+ // used for RDEN calibration: difference between shift value used during
+ // calibration, and shift value for actual RDEN SRL. Only applies when
+ // RDEN edge is immediately captured by CLKDIV0. If not (depends on phase
+ // of CLK0 and CLKDIV0 when RDEN is asserted), then add 1 to this value.
+ localparam CAL3_RDEN_SRL_DLY_DELTA = 6;
+ // fix minimum value of DQS to be 1 to handle the case where's there's only
+ // one DQS group. We could also enforce that user always inputs minimum
+ // value of 1 for DQS_BITS (even when DQS_WIDTH=1). Leave this as safeguard
+ // Assume we don't have to do this for DQ, DQ_WIDTH always > 1
+ localparam DQS_BITS_FIX = (DQS_BITS == 0) ? 1 : DQS_BITS;
+ // how many taps to "pre-delay" DQ before stg 1 calibration - not needed for
+ // current calibration, but leave for debug
+ localparam DQ_IDEL_INIT = 6'b000000;
+ // # IDELAY taps per bit time (i.e. half cycle). Limit to 63.
+ localparam integer BIT_TIME_TAPS = (CLK_PERIOD/150 < 64) ?
+ CLK_PERIOD/150 : 63;
+
+ // used in various places during stage 4 cal: (1) determines maximum taps
+ // to increment when finding right edge, (2) amount to decrement after
+ // finding left edge, (3) amount to increment after finding right edge
+ localparam CAL4_IDEL_BIT_VAL = (BIT_TIME_TAPS >= 6'b100000) ?
+ 6'b100000 : BIT_TIME_TAPS;
+
+ localparam CAL1_IDLE = 4'h0;
+ localparam CAL1_INIT = 4'h1;
+ localparam CAL1_INC_IDEL = 4'h2;
+ localparam CAL1_FIND_FIRST_EDGE = 4'h3;
+ localparam CAL1_FIRST_EDGE_IDEL_WAIT = 4'h4;
+ localparam CAL1_FOUND_FIRST_EDGE_WAIT = 4'h5;
+ localparam CAL1_FIND_SECOND_EDGE = 4'h6;
+ localparam CAL1_SECOND_EDGE_IDEL_WAIT = 4'h7;
+ localparam CAL1_CALC_IDEL = 4'h8;
+ localparam CAL1_DEC_IDEL = 4'h9;
+ localparam CAL1_DONE = 4'hA;
+
+ localparam CAL2_IDLE = 4'h0;
+ localparam CAL2_INIT = 4'h1;
+ localparam CAL2_INIT_IDEL_WAIT = 4'h2;
+ localparam CAL2_FIND_EDGE_POS = 4'h3;
+ localparam CAL2_FIND_EDGE_IDEL_WAIT_POS = 4'h4;
+ localparam CAL2_FIND_EDGE_NEG = 4'h5;
+ localparam CAL2_FIND_EDGE_IDEL_WAIT_NEG = 4'h6;
+ localparam CAL2_DEC_IDEL = 4'h7;
+ localparam CAL2_DONE = 4'h8;
+
+ localparam CAL3_IDLE = 3'h0;
+ localparam CAL3_INIT = 3'h1;
+ localparam CAL3_DETECT = 3'h2;
+ localparam CAL3_RDEN_PIPE_CLR_WAIT = 3'h3;
+ localparam CAL3_DONE = 3'h4;
+
+ localparam CAL4_IDLE = 3'h0;
+ localparam CAL4_INIT = 3'h1;
+ localparam CAL4_FIND_WINDOW = 3'h2;
+ localparam CAL4_FIND_EDGE = 3'h3;
+ localparam CAL4_IDEL_WAIT = 3'h4;
+ localparam CAL4_RDEN_PIPE_CLR_WAIT = 3'h5;
+ localparam CAL4_ADJ_IDEL = 3'h6;
+ localparam CAL4_DONE = 3'h7;
+
+ integer i, j;
+
+ reg [5:0] cal1_bit_time_tap_cnt;
+ reg [1:0] cal1_data_chk_last;
+ reg cal1_data_chk_last_valid;
+ reg [1:0] cal1_data_chk_r;
+ reg cal1_dlyce_dq;
+ reg cal1_dlyinc_dq;
+ reg cal1_dqs_dq_init_phase;
+ reg cal1_detect_edge;
+ reg cal1_detect_stable;
+ reg cal1_found_second_edge;
+ reg cal1_found_rising;
+ reg cal1_found_window;
+ reg cal1_first_edge_done;
+ reg [5:0] cal1_first_edge_tap_cnt;
+ reg [6:0] cal1_idel_dec_cnt;
+ reg [5:0] cal1_idel_inc_cnt;
+ reg [5:0] cal1_idel_max_tap;
+ reg cal1_idel_max_tap_we;
+ reg [5:0] cal1_idel_tap_cnt;
+ reg cal1_idel_tap_limit_hit;
+ reg [6:0] cal1_low_freq_idel_dec;
+ reg cal1_ref_req;
+ wire cal1_refresh;
+ reg [3:0] cal1_state;
+ reg [3:0] cal1_window_cnt;
+ reg cal2_curr_sel;
+ wire cal2_detect_edge;
+ reg cal2_dlyce_dqs;
+ reg cal2_dlyinc_dqs;
+ reg [5:0] cal2_idel_dec_cnt;
+ reg [5:0] cal2_idel_tap_cnt;
+ reg [5:0] cal2_idel_tap_limit;
+ reg cal2_idel_tap_limit_hit;
+ reg cal2_rd_data_fall_last_neg;
+ reg cal2_rd_data_fall_last_pos;
+ reg cal2_rd_data_last_valid_neg;
+ reg cal2_rd_data_last_valid_pos;
+ reg cal2_rd_data_rise_last_neg;
+ reg cal2_rd_data_rise_last_pos;
+ reg [DQS_WIDTH-1:0] cal2_rd_data_sel;
+ wire cal2_rd_data_sel_edge;
+ reg [DQS_WIDTH-1:0] cal2_rd_data_sel_r;
+ reg cal2_ref_req;
+ reg [3:0] cal2_state;
+ reg cal3_data_match;
+ reg cal3_data_match_stgd;
+ wire cal3_data_valid;
+ wire cal3_match_found;
+ wire [4:0] cal3_rden_dly;
+ reg [4:0] cal3_rden_srl_a;
+ reg [2:0] cal3_state;
+ wire cal4_data_good;
+ reg cal4_data_match;
+ reg cal4_data_match_stgd;
+ wire cal4_data_valid;
+ reg cal4_dlyce_gate;
+ reg cal4_dlyinc_gate;
+ reg cal4_dlyrst_gate;
+ reg [4:0] cal4_gate_srl_a;
+ reg [5:0] cal4_idel_adj_cnt;
+ reg cal4_idel_adj_inc;
+ reg cal4_idel_bit_tap;
+ reg [5:0] cal4_idel_tap_cnt;
+ reg cal4_idel_max_tap;
+ reg [4:0] cal4_rden_srl_a;
+ reg cal4_ref_req;
+ reg cal4_seek_left;
+ reg cal4_stable_window;
+ reg [2:0] cal4_state;
+ reg [3:0] cal4_window_cnt;
+ reg [3:0] calib_done_tmp; // only for stg1/2/4
+ reg calib_ctrl_gate_pulse_r;
+ reg calib_ctrl_rden;
+ reg calib_ctrl_rden_r;
+ wire calib_ctrl_rden_negedge;
+ reg calib_ctrl_rden_negedge_r;
+ reg [3:0] calib_done_r;
+ reg [3:0] calib_err;
+ reg [1:0] calib_err_2;
+ wire calib_init_gate_pulse;
+ reg calib_init_gate_pulse_r;
+ reg calib_init_gate_pulse_r1;
+ reg calib_init_rden;
+ reg calib_init_rden_r;
+ reg [4:0] calib_rden_srl_a;
+ wire [4:0] calib_rden_srl_a_r;
+ reg [(5*DQS_WIDTH)-1:0] calib_rden_dly;
+ reg calib_rden_edge_r;
+ reg [4:0] calib_rden_pipe_cnt;
+ wire calib_rden_srl_out;
+ wire calib_rden_srl_out_r;
+ reg calib_rden_srl_out_r1;
+ reg calib_rden_valid;
+ reg calib_rden_valid_stgd;
+ reg [DQ_BITS-1:0] count_dq;
+ reg [DQS_BITS_FIX-1:0] count_dqs;
+ reg [DQS_BITS_FIX-1:0] count_gate;
+ reg [DQS_BITS_FIX-1:0] count_rden;
+ reg ctrl_rden_r;
+ wire dlyce_or;
+ reg [(5*DQS_WIDTH)-1:0] gate_dly;
+ wire [(5*DQS_WIDTH)-1:0] gate_dly_r;
+ wire gate_srl_in;
+ wire [DQS_WIDTH-1:0] gate_srl_out;
+ wire [DQS_WIDTH-1:0] gate_srl_out_r;
+ reg [2:0] idel_set_cnt;
+ wire idel_set_wait;
+ reg [DQ_BITS-1:0] next_count_dq;
+ reg [DQS_BITS_FIX-1:0] next_count_dqs;
+ reg [DQS_BITS_FIX-1:0] next_count_gate;
+ reg phy_init_rden_r;
+ reg phy_init_rden_r1;
+ reg [DQS_WIDTH-1:0] rd_data_fall_1x_bit1_r1;
+ reg [DQ_WIDTH-1:0] rd_data_fall_1x_r;
+ reg [DQS_WIDTH-1:0] rd_data_fall_1x_r1;
+ reg [DQS_WIDTH-1:0] rd_data_fall_2x_bit1_r;
+ reg [DQS_WIDTH-1:0] rd_data_fall_2x_r;
+ wire [DQS_WIDTH-1:0] rd_data_fall_chk_q1;
+ wire [DQS_WIDTH-1:0] rd_data_fall_chk_q1_bit1;
+ wire [DQS_WIDTH-1:0] rd_data_fall_chk_q2;
+ wire [DQS_WIDTH-1:0] rd_data_fall_chk_q2_bit1;
+ reg [DQS_WIDTH-1:0] rd_data_rise_1x_bit1_r1;
+ reg [DQ_WIDTH-1:0] rd_data_rise_1x_r;
+ reg [DQS_WIDTH-1:0] rd_data_rise_1x_r1;
+ reg [DQS_WIDTH-1:0] rd_data_rise_2x_bit1_r;
+ reg [DQS_WIDTH-1:0] rd_data_rise_2x_r;
+ wire [DQS_WIDTH-1:0] rd_data_rise_chk_q1;
+ wire [DQS_WIDTH-1:0] rd_data_rise_chk_q1_bit1;
+ wire [DQS_WIDTH-1:0] rd_data_rise_chk_q2;
+ wire [DQS_WIDTH-1:0] rd_data_rise_chk_q2_bit1;
+ reg rdd_fall_q1;
+ reg rdd_fall_q1_bit1;
+ reg rdd_fall_q1_bit1_r;
+ reg rdd_fall_q1_bit1_r1;
+ reg rdd_fall_q1_r;
+ reg rdd_fall_q1_r1;
+ reg rdd_fall_q2;
+ reg rdd_fall_q2_bit1;
+ reg rdd_fall_q2_bit1_r;
+ reg rdd_fall_q2_r;
+ reg rdd_rise_q1;
+ reg rdd_rise_q1_bit1;
+ reg rdd_rise_q1_bit1_r;
+ reg rdd_rise_q1_bit1_r1;
+ reg rdd_rise_q1_r;
+ reg rdd_rise_q1_r1;
+ reg rdd_rise_q2;
+ reg rdd_rise_q2_bit1;
+ reg rdd_rise_q2_bit1_r;
+ reg rdd_rise_q2_r;
+ reg [DQS_BITS_FIX-1:0] rdd_mux_sel;
+ reg rden_dec;
+ reg [(5*DQS_WIDTH)-1:0] rden_dly;
+ wire [(5*DQS_WIDTH)-1:0] rden_dly_r;
+ reg [4:0] rden_dly_0;
+ reg rden_inc;
+ reg [DQS_WIDTH-1:0] rden_mux;
+ wire [DQS_WIDTH-1:0] rden_srl_out;
+
+ // Debug
+ integer x;
+ reg [5:0] dbg_dq_tap_cnt [DQ_WIDTH-1:0];
+ reg [5:0] dbg_dqs_tap_cnt [DQS_WIDTH-1:0];
+ reg [5:0] dbg_gate_tap_cnt [DQS_WIDTH-1:0];
+
+ //***************************************************************************
+ // Debug output ("dbg_phy_calib_*")
+ // NOTES:
+ // 1. All debug outputs coming out of PHY_CALIB are clocked off CLKDIV0,
+ // although they are also static after calibration is complete. This
+ // means the user can either connect them to a Chipscope ILA, or to
+ // either a sync/async VIO input block. Using an async VIO has the
+ // advantage of not requiring these paths to meet cycle-to-cycle timing.
+ // 2. The widths of most of these debug buses are dependent on the # of
+ // DQS/DQ bits (e.g. dq_tap_cnt width = 6 * (# of DQ bits)
+ // SIGNAL DESCRIPTION:
+ // 1. calib_done: 4 bits - each one asserted as each phase of calibration
+ // is completed.
+ // 2. calib_err: 4 bits - each one asserted when a calibration error
+ // encountered for that stage. Some of these bits may not
+ // be used (not all cal stages report an error).
+ // 3. dq_tap_cnt: final IDELAY tap counts for all DQ IDELAYs
+ // 4. dqs_tap_cnt: final IDELAY tap counts for all DQS IDELAYs
+ // 5. gate_tap_cnt: final IDELAY tap counts for all DQS gate
+ // synchronization IDELAYs
+ // 6. rd_data_sel: final read capture MUX (either "positive" or "negative"
+ // edge capture) settings for all DQS groups
+ // 7. rden_dly: related to # of cycles after issuing a read until when
+ // read data is valid - for all DQS groups
+ // 8. gate_dly: related to # of cycles after issuing a read until when
+ // clock enable for all DQ's is deasserted to prevent
+ // effect of DQS postamble glitch - for all DQS groups
+ //***************************************************************************
+
+ //*****************************************************************
+ // Record IDELAY tap values by "snooping" IDELAY control signals
+ //*****************************************************************
+
+ // record DQ IDELAY tap values
+ genvar dbg_dq_tc_i;
+ generate
+ for (dbg_dq_tc_i = 0; dbg_dq_tc_i < DQ_WIDTH;
+ dbg_dq_tc_i = dbg_dq_tc_i + 1) begin: gen_dbg_dq_tap_cnt
+ assign dbg_calib_dq_tap_cnt[(6*dbg_dq_tc_i)+5:(6*dbg_dq_tc_i)]
+ = dbg_dq_tap_cnt[dbg_dq_tc_i];
+ always @(posedge clkdiv)
+ if (rstdiv | dlyrst_dq)
+ dbg_dq_tap_cnt[dbg_dq_tc_i] <= 6'b000000;
+ else
+ if (dlyce_dq[dbg_dq_tc_i])
+ if (dlyinc_dq[dbg_dq_tc_i])
+ dbg_dq_tap_cnt[dbg_dq_tc_i]
+ <= dbg_dq_tap_cnt[dbg_dq_tc_i] + 1;
+ else
+ dbg_dq_tap_cnt[dbg_dq_tc_i]
+ <= dbg_dq_tap_cnt[dbg_dq_tc_i] - 1;
+ end
+ endgenerate
+
+ // record DQS IDELAY tap values
+ genvar dbg_dqs_tc_i;
+ generate
+ for (dbg_dqs_tc_i = 0; dbg_dqs_tc_i < DQS_WIDTH;
+ dbg_dqs_tc_i = dbg_dqs_tc_i + 1) begin: gen_dbg_dqs_tap_cnt
+ assign dbg_calib_dqs_tap_cnt[(6*dbg_dqs_tc_i)+5:(6*dbg_dqs_tc_i)]
+ = dbg_dqs_tap_cnt[dbg_dqs_tc_i];
+ always @(posedge clkdiv)
+ if (rstdiv | dlyrst_dqs)
+ dbg_dqs_tap_cnt[dbg_dqs_tc_i] <= 6'b000000;
+ else
+ if (dlyce_dqs[dbg_dqs_tc_i])
+ if (dlyinc_dqs[dbg_dqs_tc_i])
+ dbg_dqs_tap_cnt[dbg_dqs_tc_i]
+ <= dbg_dqs_tap_cnt[dbg_dqs_tc_i] + 1;
+ else
+ dbg_dqs_tap_cnt[dbg_dqs_tc_i]
+ <= dbg_dqs_tap_cnt[dbg_dqs_tc_i] - 1;
+ end
+ endgenerate
+
+ // record DQS gate IDELAY tap values
+ genvar dbg_gate_tc_i;
+ generate
+ for (dbg_gate_tc_i = 0; dbg_gate_tc_i < DQS_WIDTH;
+ dbg_gate_tc_i = dbg_gate_tc_i + 1) begin: gen_dbg_gate_tap_cnt
+ assign dbg_calib_gate_tap_cnt[(6*dbg_gate_tc_i)+5:(6*dbg_gate_tc_i)]
+ = dbg_gate_tap_cnt[dbg_gate_tc_i];
+ always @(posedge clkdiv)
+ if (rstdiv | dlyrst_gate[dbg_gate_tc_i])
+ dbg_gate_tap_cnt[dbg_gate_tc_i] <= 6'b000000;
+ else
+ if (dlyce_gate[dbg_gate_tc_i])
+ if (dlyinc_gate[dbg_gate_tc_i])
+ dbg_gate_tap_cnt[dbg_gate_tc_i]
+ <= dbg_gate_tap_cnt[dbg_gate_tc_i] + 1;
+ else
+ dbg_gate_tap_cnt[dbg_gate_tc_i]
+ <= dbg_gate_tap_cnt[dbg_gate_tc_i] - 1;
+ end
+ endgenerate
+
+ assign dbg_calib_done = calib_done;
+ assign dbg_calib_err = calib_err;
+ assign dbg_calib_rd_data_sel = cal2_rd_data_sel;
+ assign dbg_calib_rden_dly = rden_dly;
+ assign dbg_calib_gate_dly = gate_dly;
+
+ //***************************************************************************
+ // Read data pipelining, and read data "ISERDES" data width expansion
+ //***************************************************************************
+
+ // For all data bits, register incoming capture data to slow clock to improve
+ // timing. Adding single pipeline stage does not affect functionality (as
+ // long as we make sure to wait extra clock cycle after changing DQ IDELAY)
+ // Also note in this case that we're "missing" every other clock cycle's
+ // worth of data capture since we're sync'ing to the slow clock. This is
+ // fine for stage 1 and stage 2 cal, but not for stage 3 and 4 (see below
+ // for different circuit to handle those stages)
+ always @(posedge clkdiv) begin
+ rd_data_rise_1x_r <= rd_data_rise;
+ rd_data_fall_1x_r <= rd_data_fall;
+ end
+
+ // For every DQ_PER_DQS bit, generate what is essentially a ISERDES-type
+ // data width expander. Will need this for stage 3 and 4 cal, where we need
+ // to compare data over consecutive clock cycles. We can also use this for
+ // stage 2 as well (stage 2 doesn't require every bit to be looked at, only
+ // one bit per DQS group)
+ // MIG 3.3: Expand to use lower two bits of each DQS group - use for stage
+ // 3 calibration for added robustness, since we will be checking for the
+ // training pattern from the memory even when the data bus is 3-stated.
+ // Theoretically it is possible for whatever garbage data is on the bus
+ // to be interpreted as the training sequence, although this can be made
+ // very unlikely by the choice of training sequence (bit sequence, length)
+ // and the number of bits compared for each DQS group.
+ genvar rdd_i;
+ generate
+ for (rdd_i = 0; rdd_i < DQS_WIDTH; rdd_i = rdd_i + 1) begin: gen_rdd
+ // first stage: keep data in fast clk domain. Store data over two
+ // consecutive clock cycles for rise/fall data for proper transfer
+ // to slow clock domain
+ always @(posedge clk) begin
+ rd_data_rise_2x_r[rdd_i] <= rd_data_rise[(rdd_i*DQ_PER_DQS)];
+ rd_data_fall_2x_r[rdd_i] <= rd_data_fall[(rdd_i*DQ_PER_DQS)];
+ rd_data_rise_2x_bit1_r[rdd_i] <= rd_data_rise[(rdd_i*DQ_PER_DQS)+1];
+ rd_data_fall_2x_bit1_r[rdd_i] <= rd_data_fall[(rdd_i*DQ_PER_DQS)+1];
+ end
+ // second stage, register first stage to slow clock domain, 2nd stage
+ // consists of both these flops, and the rd_data_rise_1x_r flops
+ always @(posedge clkdiv) begin
+ rd_data_rise_1x_r1[rdd_i] <= rd_data_rise_2x_r[rdd_i];
+ rd_data_fall_1x_r1[rdd_i] <= rd_data_fall_2x_r[rdd_i];
+ rd_data_rise_1x_bit1_r1[rdd_i] <= rd_data_rise_2x_bit1_r[rdd_i];
+ rd_data_fall_1x_bit1_r1[rdd_i] <= rd_data_fall_2x_bit1_r[rdd_i];
+ end
+ // now we have four outputs - representing rise/fall outputs over last
+ // 2 fast clock cycles. However, the ordering these represent can either
+ // be: (1) Q2 = data @ time = n, Q1 = data @ time = n+1, or (2)
+ // Q2 = data @ time = n - 1, Q1 = data @ time = n (and data at [Q1,Q2]
+ // is "staggered") - leave it up to the stage of calibration using this
+ // to figure out which is which, if they care at all (e.g. stage 2 cal
+ // doesn't care about the ordering)
+ assign rd_data_rise_chk_q1[rdd_i]
+ = rd_data_rise_1x_r[(rdd_i*DQ_PER_DQS)];
+ assign rd_data_rise_chk_q2[rdd_i]
+ = rd_data_rise_1x_r1[rdd_i];
+ assign rd_data_fall_chk_q1[rdd_i]
+ = rd_data_fall_1x_r[(rdd_i*DQ_PER_DQS)];
+ assign rd_data_fall_chk_q2[rdd_i]
+ = rd_data_fall_1x_r1[rdd_i];
+ // MIG 3.3: Added comparison for second bit in DQS group for stage 3 cal
+ assign rd_data_rise_chk_q1_bit1[rdd_i]
+ = rd_data_rise_1x_r[(rdd_i*DQ_PER_DQS)+1];
+ assign rd_data_rise_chk_q2_bit1[rdd_i]
+ = rd_data_rise_1x_bit1_r1[rdd_i];
+ assign rd_data_fall_chk_q1_bit1[rdd_i]
+ = rd_data_fall_1x_r[(rdd_i*DQ_PER_DQS)+1];
+ assign rd_data_fall_chk_q2_bit1[rdd_i]
+ = rd_data_fall_1x_bit1_r1[rdd_i];
+ end
+ endgenerate
+
+ //*****************************************************************
+ // Outputs of these simplified ISERDES circuits then feed MUXes based on
+ // which DQ the current calibration algorithm needs to look at
+ //*****************************************************************
+
+ // generate MUX control; assume that adding an extra pipeline stage isn't
+ // an issue - whatever stage cal logic is using output of MUX will wait
+ // enough time after changing it
+ always @(posedge clkdiv) begin
+ (* full_case, parallel_case *) case (calib_done[2:0])
+ 3'b001: rdd_mux_sel <= next_count_dqs;
+ 3'b011: rdd_mux_sel <= count_rden;
+ 3'b111: rdd_mux_sel <= next_count_gate;
+ default: rdd_mux_sel <= {DQS_BITS_FIX{1'bx}};
+ endcase
+ end
+
+ always @(posedge clkdiv) begin
+ rdd_rise_q1 <= rd_data_rise_chk_q1[rdd_mux_sel];
+ rdd_rise_q2 <= rd_data_rise_chk_q2[rdd_mux_sel];
+ rdd_fall_q1 <= rd_data_fall_chk_q1[rdd_mux_sel];
+ rdd_fall_q2 <= rd_data_fall_chk_q2[rdd_mux_sel];
+ rdd_rise_q1_bit1 <= rd_data_rise_chk_q1_bit1[rdd_mux_sel];
+ rdd_rise_q2_bit1 <= rd_data_rise_chk_q2_bit1[rdd_mux_sel];
+ rdd_fall_q1_bit1 <= rd_data_fall_chk_q1_bit1[rdd_mux_sel];
+ rdd_fall_q2_bit1 <= rd_data_fall_chk_q2_bit1[rdd_mux_sel];
+ end
+
+ //***************************************************************************
+ // Demultiplexor to control (reset, increment, decrement) IDELAY tap values
+ // For DQ:
+ // STG1: for per-bit-deskew, only inc/dec the current DQ. For non-per
+ // deskew, increment all bits in the current DQS set
+ // STG2: inc/dec all DQ's in the current DQS set.
+ // NOTE: Nice to add some error checking logic here (or elsewhere in the
+ // code) to check if logic attempts to overflow tap value
+ //***************************************************************************
+
+ // don't use DLYRST to reset value of IDELAY after reset. Need to change this
+ // if we want to allow user to recalibrate after initial reset
+ always @(posedge clkdiv)
+ if (rstdiv) begin
+ dlyrst_dq <= 1'b1;
+ dlyrst_dqs <= 1'b1;
+ end else begin
+ dlyrst_dq <= 1'b0;
+ dlyrst_dqs <= 1'b0;
+ end
+
+ always @(posedge clkdiv) begin
+ if (rstdiv) begin
+ dlyce_dq <= 'b0;
+ dlyinc_dq <= 'b0;
+ dlyce_dqs <= 'b0;
+ dlyinc_dqs <= 'b0;
+ end else begin
+ dlyce_dq <= 'b0;
+ dlyinc_dq <= 'b0;
+ dlyce_dqs <= 'b0;
+ dlyinc_dqs <= 'b0;
+
+ // stage 1 cal: change only specified DQ
+ if (cal1_dlyce_dq) begin
+ if (SIM_ONLY == 0) begin
+ dlyce_dq[count_dq] <= 1'b1;
+ dlyinc_dq[count_dq] <= cal1_dlyinc_dq;
+ end else begin
+ // if simulation, then calibrate only first DQ, apply results
+ // to all DQs (i.e. assume delay on all DQs is the same)
+ for (i = 0; i < DQ_WIDTH; i = i + 1) begin: loop_sim_dq_dly
+ dlyce_dq[i] <= 1'b1;
+ dlyinc_dq[i] <= cal1_dlyinc_dq;
+ end
+ end
+ end else if (cal2_dlyce_dqs) begin
+ // stage 2 cal: change DQS and all corresponding DQ's
+ if (SIM_ONLY == 0) begin
+ dlyce_dqs[count_dqs] <= 1'b1;
+ dlyinc_dqs[count_dqs] <= cal2_dlyinc_dqs;
+ for (i = 0; i < DQ_PER_DQS; i = i + 1) begin: loop_dqs_dly
+ dlyce_dq[(DQ_PER_DQS*count_dqs)+i] <= 1'b1;
+ dlyinc_dq[(DQ_PER_DQS*count_dqs)+i] <= cal2_dlyinc_dqs;
+ end
+ end else begin
+ for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_dqs_dly
+ // if simulation, then calibrate only first DQS
+ dlyce_dqs[i] <= 1'b1;
+ dlyinc_dqs[i] <= cal2_dlyinc_dqs;
+ for (j = 0; j < DQ_PER_DQS; j = j + 1) begin: loop_sim_dq_dqs_dly
+ dlyce_dq[(DQ_PER_DQS*i)+j] <= 1'b1;
+ dlyinc_dq[(DQ_PER_DQS*i)+j] <= cal2_dlyinc_dqs;
+ end
+ end
+ end
+ end else if (DEBUG_EN != 0) begin
+ // DEBUG: allow user to vary IDELAY tap settings
+ // For DQ IDELAY taps
+ if (dbg_idel_up_all || dbg_idel_down_all ||
+ dbg_sel_all_idel_dq) begin
+ for (x = 0; x < DQ_WIDTH; x = x + 1) begin: loop_dly_inc_dq
+ dlyce_dq[x] <= dbg_idel_up_all | dbg_idel_down_all |
+ dbg_idel_up_dq | dbg_idel_down_dq;
+ dlyinc_dq[x] <= dbg_idel_up_all | dbg_idel_up_dq;
+ end
+ end else begin
+ dlyce_dq <= 'b0;
+ dlyce_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq |
+ dbg_idel_down_dq;
+ dlyinc_dq[dbg_sel_idel_dq] <= dbg_idel_up_dq;
+ end
+ // For DQS IDELAY taps
+ if (dbg_idel_up_all || dbg_idel_down_all ||
+ dbg_sel_all_idel_dqs) begin
+ for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_dqs
+ dlyce_dqs[x] <= dbg_idel_up_all | dbg_idel_down_all |
+ dbg_idel_up_dqs | dbg_idel_down_dqs;
+ dlyinc_dqs[x] <= dbg_idel_up_all | dbg_idel_up_dqs;
+ end
+ end else begin
+ dlyce_dqs <= 'b0;
+ dlyce_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs |
+ dbg_idel_down_dqs;
+ dlyinc_dqs[dbg_sel_idel_dqs] <= dbg_idel_up_dqs;
+ end
+ end
+ end
+ end
+
+ // GATE synchronization is handled directly by Stage 4 calibration FSM
+ always @(posedge clkdiv)
+ if (rstdiv) begin
+ dlyrst_gate <= {DQS_WIDTH{1'b1}};
+ dlyce_gate <= {DQS_WIDTH{1'b0}};
+ dlyinc_gate <= {DQS_WIDTH{1'b0}};
+ end else begin
+ dlyrst_gate <= {DQS_WIDTH{1'b0}};
+ dlyce_gate <= {DQS_WIDTH{1'b0}};
+ dlyinc_gate <= {DQS_WIDTH{1'b0}};
+
+ if (cal4_dlyrst_gate) begin
+ if (SIM_ONLY == 0)
+ dlyrst_gate[count_gate] <= 1'b1;
+ else
+ for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly_rst
+ dlyrst_gate[i] <= 1'b1;
+ end
+ end
+
+ if (cal4_dlyce_gate) begin
+ if (SIM_ONLY == 0) begin
+ dlyce_gate[count_gate] <= 1'b1;
+ dlyinc_gate[count_gate] <= cal4_dlyinc_gate;
+ end else begin
+ // if simulation, then calibrate only first gate
+ for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_gate_sim_dly
+ dlyce_gate[i] <= 1'b1;
+ dlyinc_gate[i] <= cal4_dlyinc_gate;
+ end
+ end
+ end else if (DEBUG_EN != 0) begin
+ // DEBUG: allow user to vary IDELAY tap settings
+ if (dbg_idel_up_all || dbg_idel_down_all ||
+ dbg_sel_all_idel_gate) begin
+ for (x = 0; x < DQS_WIDTH; x = x + 1) begin: loop_dly_inc_gate
+ dlyce_gate[x] <= dbg_idel_up_all | dbg_idel_down_all |
+ dbg_idel_up_gate | dbg_idel_down_gate;
+ dlyinc_gate[x] <= dbg_idel_up_all | dbg_idel_up_gate;
+ end
+ end else begin
+ dlyce_gate <= {DQS_WIDTH{1'b0}};
+ dlyce_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate |
+ dbg_idel_down_gate;
+ dlyinc_gate[dbg_sel_idel_gate] <= dbg_idel_up_gate;
+ end
+ end
+ end
+
+ //***************************************************************************
+ // signal to tell calibration state machines to wait and give IDELAY time to
+ // settle after it's value is changed (both time for IDELAY chain to settle,
+ // and for settled output to propagate through ISERDES). For general use: use
+ // for any calibration state machines that modify any IDELAY.
+ // Should give at least enough time for IDELAY output to settle (technically
+ // for V5, this should be "glitchless" when IDELAY taps are changed, so don't
+ // need any time here), and also time for new data to propagate through both
+ // ISERDES and the "RDD" MUX + associated pipelining
+ // For now, give very "generous" delay - doesn't really matter since only
+ // needed during calibration
+ //***************************************************************************
+
+ // determine if calibration polarity has changed
+ always @(posedge clkdiv)
+ cal2_rd_data_sel_r <= cal2_rd_data_sel;
+
+ assign cal2_rd_data_sel_edge = |(cal2_rd_data_sel ^ cal2_rd_data_sel_r);
+
+ // combine requests to modify any of the IDELAYs into one. Also when second
+ // stage capture "edge" polarity is changed (IDELAY isn't changed in this
+ // case, but use the same counter to stall cal logic)
+ assign dlyce_or = cal1_dlyce_dq |
+ cal2_dlyce_dqs |
+ cal2_rd_data_sel_edge |
+ cal4_dlyce_gate |
+ cal4_dlyrst_gate;
+
+ // SYN_NOTE: Can later recode to avoid combinational path
+ assign idel_set_wait = dlyce_or || (idel_set_cnt != IDEL_SET_VAL);
+
+ always @(posedge clkdiv)
+ if (rstdiv)
+ idel_set_cnt <= 4'b0000;
+ else if (dlyce_or)
+ idel_set_cnt <= 4'b0000;
+ else if (idel_set_cnt != IDEL_SET_VAL)
+ idel_set_cnt <= idel_set_cnt + 1;
+
+ // generate request to PHY_INIT logic to issue auto-refresh
+ // used by certain states to force prech/auto-refresh part way through
+ // calibration to avoid a tRAS violation (which will happen if that
+ // stage of calibration lasts long enough). This signal must meet the
+ // following requirements: (1) only transition from 0->1 when the refresh
+ // request is needed, (2) stay at 1 and only transition 1->0 when
+ // CALIB_REF_DONE is asserted
+ always @(posedge clkdiv)
+ if (rstdiv)
+ calib_ref_req <= 1'b0;
+ else
+ calib_ref_req <= cal1_ref_req | cal2_ref_req | cal4_ref_req;
+
+ // stage 1 calibration requests auto-refresh every 4 bits
+ generate
+ if (DQ_BITS < 2) begin: gen_cal1_refresh_dq_lte4
+ assign cal1_refresh = 1'b0;
+ end else begin: gen_cal1_refresh_dq_gt4
+ assign cal1_refresh = (next_count_dq[1:0] == 2'b00);
+ end
+ endgenerate
+
+ //***************************************************************************
+ // First stage calibration: DQ-DQS
+ // Definitions:
+ // edge: detected when varying IDELAY, and current capture data != prev
+ // capture data
+ // valid bit window: detected when current capture data == prev capture
+ // data for more than half the bit time
+ // starting conditions for DQS-DQ phase:
+ // case 1: when DQS starts somewhere in rising edge bit window, or
+ // on the right edge of the rising bit window.
+ // case 2: when DQS starts somewhere in falling edge bit window, or
+ // on the right edge of the falling bit window.
+ // Algorithm Description:
+ // 1. Increment DQ IDELAY until we find an edge.
+ // 2. While we're finding the first edge, note whether a valid bit window
+ // has been detected before we found an edge. If so, then figure out if
+ // this is the rising or falling bit window. If rising, then our starting
+ // DQS-DQ phase is case 1. If falling, then it's case 2. If don't detect
+ // a valid bit window, then we must have started on the edge of a window.
+ // Need to wait until later on to decide which case we are.
+ // - Store FIRST_EDGE IDELAY value
+ // 3. Now look for second edge.
+ // 4. While we're finding the second edge, note whether valid bit window
+ // is detected. If so, then use to, along with results from (2) to figure
+ // out what the starting case is. If in rising bit window, then we're in
+ // case 2. If falling, then case 1.
+ // - Store SECOND_EDGE IDELAY value
+ // NOTES:
+ // a. Finding two edges allows us to calculate the bit time (although
+ // not the "same" bit time polarity - need to investigate this
+ // more).
+ // b. If we run out of taps looking for the second edge, then the bit
+ // time must be too long (>= 2.5ns, and DQS-DQ starting phase must be
+ // case 1).
+ // 5. Calculate absolute amount to delay DQ as:
+ // If second edge found, and case 1:
+ // - DQ_IDELAY = FIRST_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
+ // If second edge found, and case 2:
+ // - DQ_IDELAY = SECOND_EDGE - 0.5*(SECOND_EDGE - FIRST_EDGE)
+ // If second edge not found, then need to make an approximation on
+ // how much to shift by (should be okay, because we have more timing
+ // margin):
+ // - DQ_IDELAY = FIRST_EDGE - 0.5 * (bit_time)
+ // NOTE: Does this account for either case 1 or case 2?????
+ // NOTE: It's also possible even when we find the second edge, that
+ // to instead just use half the bit time to subtract from either
+ // FIRST or SECOND_EDGE. Finding the actual bit time (which is
+ // what (SECOND_EDGE - FIRST_EDGE) is, is slightly more accurate,
+ // since it takes into account duty cycle distortion.
+ // 6. Repeat for each DQ in current DQS set.
+ //***************************************************************************
+
+ //*****************************************************************
+ // for first stage calibration - used for checking if DQS is aligned to the
+ // particular DQ, such that we're in the data valid window. Basically, this
+ // is one giant MUX.
+ // = [falling data, rising data]
+ // = [0, 1] = rising DQS aligned in proper (rising edge) bit window
+ // = [1, 0] = rising DQS aligned in wrong (falling edge) bit window
+ // = [0, 0], or [1,1] = in uncertain region between windows
+ //*****************************************************************
+
+ // SYN_NOTE: May have to split this up into multiple levels - MUX can get
+ // very wide - as wide as the data bus width
+ always @(posedge clkdiv)
+ cal1_data_chk_r <= {rd_data_fall_1x_r[next_count_dq],
+ rd_data_rise_1x_r[next_count_dq]};
+
+ //*****************************************************************
+ // determine when an edge has occurred - when either the current value
+ // is different from the previous latched value or when the DATA_CHK
+ // outputs are the same (rare, but indicates that we're at an edge)
+ // This is only valid when the IDELAY output and propagation of the
+ // data through the capture flops has had a chance to settle out.
+ //*****************************************************************
+
+ // write CAL1_DETECT_EDGE and CAL1_DETECT_STABLE in such a way that
+ // if X's are captured on the bus during functional simulation, that
+ // the logic will register this as an edge detected. Do this to allow
+ // use of this HDL with Denali memory models (Denali models drive DQ
+ // to X's on both edges of the data valid window to simulate jitter)
+ // This is only done for functional simulation purposes. **Should not**
+ // make the final synthesized logic more complicated, but it does make
+ // the HDL harder to understand b/c we have to "phrase" the logic
+ // slightly differently than when not worrying about X's
+ always @(*) begin
+ // no edge found if: (1) we have recorded prev edge, and rise
+ // data == fall data, (2) we haven't yet recorded prev edge, but
+ // rise/fall data is equal to either [0,1] or [1,0] (i.e. rise/fall
+ // data isn't either X's, or [0,0] or [1,1], which indicates we're
+ // in the middle of an edge, since normally rise != fall data for stg1)
+ if ((cal1_data_chk_last_valid &&
+ (cal1_data_chk_r == cal1_data_chk_last)) ||
+ (!cal1_data_chk_last_valid &&
+ ((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10))))
+ cal1_detect_edge = 1'b0;
+ else
+ cal1_detect_edge = 1'b1;
+ end
+
+ always @(*) begin
+ // assert if we've found a region where data valid window is stable
+ // over consecutive IDELAY taps, and either rise/fall = [1,0], or [0,1]
+ if ((cal1_data_chk_last_valid &&
+ (cal1_data_chk_r == cal1_data_chk_last)) &&
+ ((cal1_data_chk_r == 2'b01) || (cal1_data_chk_r == 2'b10)))
+ cal1_detect_stable = 1'b1;
+ else
+ cal1_detect_stable = 1'b0;
+ end
+
+ //*****************************************************************
+ // Find valid window: keep track of how long we've been in the same data
+ // window. If it's been long enough, then declare that we've found a valid
+ // window. Also returns whether we found a rising or falling window (only
+ // valid when found_window is asserted)
+ //*****************************************************************
+
+ always @(posedge clkdiv) begin
+ if (cal1_state == CAL1_INIT) begin
+ cal1_window_cnt <= 4'b0000;
+ cal1_found_window <= 1'b0;
+ cal1_found_rising <= 1'bx;
+ end else if (!cal1_data_chk_last_valid) begin
+ // if we haven't stored a previous value of CAL1_DATA_CHK (or it got
+ // invalidated because we detected an edge, and are now looking for the
+ // second edge), then make sure FOUND_WINDOW deasserted on following
+ // clock edge (to avoid finding a false window immediately after finding
+ // an edge). Note that because of jitter, it's possible to not find an
+ // edge at the end of the IDELAY increment settling time, but to find an
+ // edge on the next clock cycle (e.g. during CAL1_FIND_FIRST_EDGE)
+ cal1_window_cnt <= 4'b0000;
+ cal1_found_window <= 1'b0;
+ cal1_found_rising <= 1'bx;
+ end else if (((cal1_state == CAL1_FIRST_EDGE_IDEL_WAIT) ||
+ (cal1_state == CAL1_SECOND_EDGE_IDEL_WAIT)) &&
+ !idel_set_wait) begin
+ // while finding the first and second edges, see if we can detect a
+ // stable bit window (occurs over MIN_WIN_SIZE number of taps). If
+ // so, then we're away from an edge, and can conclusively determine the
+ // starting DQS-DQ phase.
+ if (cal1_detect_stable) begin
+ cal1_window_cnt <= cal1_window_cnt + 1;
+ if (cal1_window_cnt == MIN_WIN_SIZE-1) begin
+ cal1_found_window <= 1'b1;
+ if (cal1_data_chk_r == 2'b01)
+ cal1_found_rising <= 1'b1;
+ else
+ cal1_found_rising <= 1'b0;
+ end
+ end else begin
+ // otherwise, we're not in a data valid window, reset the window
+ // counter, and indicate we're not currently in window. This should
+ // happen by design at least once after finding the first edge.
+ cal1_window_cnt <= 4'b0000;
+ cal1_found_window <= 1'b0;
+ cal1_found_rising <= 1'bx;
+ end
+ end
+ end
+
+ //*****************************************************************
+ // keep track of edge tap counts found, and whether we've
+ // incremented to the maximum number of taps allowed
+ //*****************************************************************
+
+ always @(posedge clkdiv)
+ if (cal1_state == CAL1_INIT) begin
+ cal1_idel_tap_limit_hit <= 1'b0;
+ cal1_idel_tap_cnt <= 6'b000000;
+ end else if (cal1_dlyce_dq) begin
+ if (cal1_dlyinc_dq) begin
+ cal1_idel_tap_cnt <= cal1_idel_tap_cnt + 1;
+ cal1_idel_tap_limit_hit <= (cal1_idel_tap_cnt == 6'b111110);
+ end else begin
+ cal1_idel_tap_cnt <= cal1_idel_tap_cnt - 1;
+ cal1_idel_tap_limit_hit <= 1'b0;
+ end
+ end
+
+ //*****************************************************************
+ // Pipeline for better timing - amount to decrement by if second
+ // edge not found
+ //*****************************************************************
+ // if only one edge found (possible for low frequencies), then:
+ // 1. Assume starting DQS-DQ phase has DQS in DQ window (aka "case 1")
+ // 2. We have to decrement by (63 - first_edge_tap_cnt) + (BIT_TIME_TAPS/2)
+ // (i.e. decrement by 63-first_edge_tap_cnt to get to right edge of
+ // DQ window. Then decrement again by (BIT_TIME_TAPS/2) to get to center
+ // of DQ window.
+ // 3. Clamp the above value at 63 to ensure we don't underflow IDELAY
+ // (note: clamping happens in the CAL1 state machine)
+ always @(posedge clkdiv)
+ cal1_low_freq_idel_dec
+ <= (7'b0111111 - {1'b0, cal1_first_edge_tap_cnt}) +
+ (BIT_TIME_TAPS/2);
+
+ //*****************************************************************
+ // Keep track of max taps used during stage 1, use this to limit
+ // the number of taps that can be used in stage 2
+ //*****************************************************************
+
+ always @(posedge clkdiv)
+ if (rstdiv) begin
+ cal1_idel_max_tap <= 6'b000000;
+ cal1_idel_max_tap_we <= 1'b0;
+ end else begin
+ // pipeline latch enable for CAL1_IDEL_MAX_TAP - we have plenty
+ // of time, tap count gets updated, then dead cycles waiting for
+ // IDELAY output to settle
+ cal1_idel_max_tap_we <= (cal1_idel_max_tap < cal1_idel_tap_cnt);
+ // record maximum # of taps used for stg 1 cal
+ if ((cal1_state == CAL1_DONE) && cal1_idel_max_tap_we)
+ cal1_idel_max_tap <= cal1_idel_tap_cnt;
+ end
+
+ //*****************************************************************
+
+ always @(posedge clkdiv)
+ if (rstdiv) begin
+ calib_done[0] <= 1'b0;
+ calib_done_tmp[0] <= 1'bx;
+ calib_err[0] <= 1'b0;
+ count_dq <= {DQ_BITS{1'b0}};
+ next_count_dq <= {DQ_BITS{1'b0}};
+ cal1_bit_time_tap_cnt <= 6'bxxxxxx;
+ cal1_data_chk_last <= 2'bxx;
+ cal1_data_chk_last_valid <= 1'bx;
+ cal1_dlyce_dq <= 1'b0;
+ cal1_dlyinc_dq <= 1'b0;
+ cal1_dqs_dq_init_phase <= 1'bx;
+ cal1_first_edge_done <= 1'bx;
+ cal1_found_second_edge <= 1'bx;
+ cal1_first_edge_tap_cnt <= 6'bxxxxxx;
+ cal1_idel_dec_cnt <= 7'bxxxxxxx;
+ cal1_idel_inc_cnt <= 6'bxxxxxx;
+ cal1_ref_req <= 1'b0;
+ cal1_state <= CAL1_IDLE;
+ end else begin
+ // default values for all "pulse" outputs
+ cal1_ref_req <= 1'b0;
+ cal1_dlyce_dq <= 1'b0;
+ cal1_dlyinc_dq <= 1'b0;
+
+ case (cal1_state)
+ CAL1_IDLE: begin
+ count_dq <= {DQ_BITS{1'b0}};
+ next_count_dq <= {DQ_BITS{1'b0}};
+ if (calib_start[0]) begin
+ calib_done[0] <= 1'b0;
+ calib_done_tmp[0] <= 1'b0;
+ cal1_state <= CAL1_INIT;
+ end
+ end
+
+ CAL1_INIT: begin
+ cal1_data_chk_last_valid <= 1'b0;
+ cal1_found_second_edge <= 1'b0;
+ cal1_dqs_dq_init_phase <= 1'b0;
+ cal1_idel_inc_cnt <= 6'b000000;
+ cal1_state <= CAL1_INC_IDEL;
+ end
+
+ // increment DQ IDELAY so that either: (1) DQS starts somewhere in
+ // first rising DQ window, or (2) DQS starts in first falling DQ
+ // window. The amount to shift is frequency dependent (and is either
+ // precalculated by MIG or possibly adjusted by the user)
+ CAL1_INC_IDEL:
+ if ((cal1_idel_inc_cnt == DQ_IDEL_INIT) && !idel_set_wait) begin
+ cal1_state <= CAL1_FIND_FIRST_EDGE;
+ end else if (cal1_idel_inc_cnt != DQ_IDEL_INIT) begin
+ cal1_idel_inc_cnt <= cal1_idel_inc_cnt + 1;
+ cal1_dlyce_dq <= 1'b1;
+ cal1_dlyinc_dq <= 1'b1;
+ end
+
+ // look for first edge
+ CAL1_FIND_FIRST_EDGE: begin
+ // Determine DQS-DQ phase if we can detect enough of a valid window
+ if (cal1_found_window)
+ cal1_dqs_dq_init_phase <= ~cal1_found_rising;
+ // find first edge - if found then record position
+ if (cal1_detect_edge) begin
+ cal1_state <= CAL1_FOUND_FIRST_EDGE_WAIT;
+ cal1_first_edge_done <= 1'b0;
+ cal1_first_edge_tap_cnt <= cal1_idel_tap_cnt;
+ cal1_data_chk_last_valid <= 1'b0;
+ end else begin
+ // otherwise, store the current value of DATA_CHK, increment
+ // DQ IDELAY, and compare again
+ cal1_state <= CAL1_FIRST_EDGE_IDEL_WAIT;
+ cal1_data_chk_last <= cal1_data_chk_r;
+ // avoid comparing against DATA_CHK_LAST for previous iteration
+ cal1_data_chk_last_valid <= 1'b1;
+ cal1_dlyce_dq <= 1'b1;
+ cal1_dlyinc_dq <= 1'b1;
+ end
+ end
+
+ // wait for DQ IDELAY to settle
+ CAL1_FIRST_EDGE_IDEL_WAIT:
+ if (!idel_set_wait)
+ cal1_state <= CAL1_FIND_FIRST_EDGE;
+
+ // delay state between finding first edge and looking for second
+ // edge. Necessary in order to invalidate CAL1_FOUND_WINDOW before
+ // starting to look for second edge
+ CAL1_FOUND_FIRST_EDGE_WAIT:
+ cal1_state <= CAL1_FIND_SECOND_EDGE;
+
+ // Try and find second edge
+ CAL1_FIND_SECOND_EDGE: begin
+ // When looking for 2nd edge, first make sure data stabilized (by
+ // detecting valid data window) - needed to avoid false edges
+ if (cal1_found_window) begin
+ cal1_first_edge_done <= 1'b1;
+ cal1_dqs_dq_init_phase <= cal1_found_rising;
+ end
+ // exit if run out of taps to increment
+ if (cal1_idel_tap_limit_hit)
+ cal1_state <= CAL1_CALC_IDEL;
+ else begin
+ // found second edge, record the current edge count
+ if (cal1_first_edge_done && cal1_detect_edge) begin
+ cal1_state <= CAL1_CALC_IDEL;
+ cal1_found_second_edge <= 1'b1;
+ cal1_bit_time_tap_cnt <= cal1_idel_tap_cnt -
+ cal1_first_edge_tap_cnt + 1;
+ end else begin
+ cal1_state <= CAL1_SECOND_EDGE_IDEL_WAIT;
+ cal1_data_chk_last <= cal1_data_chk_r;
+ cal1_data_chk_last_valid <= 1'b1;
+ cal1_dlyce_dq <= 1'b1;
+ cal1_dlyinc_dq <= 1'b1;
+ end
+ end
+ end
+
+ // wait for DQ IDELAY to settle, then store ISERDES output
+ CAL1_SECOND_EDGE_IDEL_WAIT:
+ if (!idel_set_wait)
+ cal1_state <= CAL1_FIND_SECOND_EDGE;
+
+ // pipeline delay state to calculate amount to decrement DQ IDELAY
+ // NOTE: We're calculating the amount to decrement by, not the
+ // absolute setting for DQ IDELAY
+ CAL1_CALC_IDEL: begin
+ // if two edges found
+ if (cal1_found_second_edge)
+ // case 1: DQS was in DQ window to start with. First edge found
+ // corresponds to left edge of DQ rising window. Backup by 1.5*BT
+ // NOTE: In this particular case, it is possible to decrement
+ // "below 0" in the case where DQS delay is less than 0.5*BT,
+ // need to limit decrement to prevent IDELAY tap underflow
+ if (!cal1_dqs_dq_init_phase)
+ cal1_idel_dec_cnt <= {1'b0, cal1_bit_time_tap_cnt} +
+ {1'b0, (cal1_bit_time_tap_cnt >> 1)};
+ // case 2: DQS was in wrong DQ window (in DQ falling window).
+ // First edge found is right edge of DQ rising window. Second
+ // edge is left edge of DQ rising window. Backup by 0.5*BT
+ else
+ cal1_idel_dec_cnt <= {1'b0, (cal1_bit_time_tap_cnt >> 1)};
+ // if only one edge found - assume will always be case 1 - DQS in
+ // DQS window. Case 2 only possible if path delay on DQS > 5ns
+ else
+ cal1_idel_dec_cnt <= cal1_low_freq_idel_dec;
+ cal1_state <= CAL1_DEC_IDEL;
+ end
+
+ // decrement DQ IDELAY for final adjustment
+ CAL1_DEC_IDEL:
+ // once adjustment is complete, we're done with calibration for
+ // this DQ, now return to IDLE state and repeat for next DQ
+ // Add underflow protection for case of 2 edges found and DQS
+ // starting in DQ window (see comments for above state) - note we
+ // have to take into account delayed value of CAL1_IDEL_TAP_CNT -
+ // gets updated one clock cycle after CAL1_DLYCE/INC_DQ
+ if ((cal1_idel_dec_cnt == 7'b0000000) ||
+ (cal1_dlyce_dq && (cal1_idel_tap_cnt == 6'b000001))) begin
+ cal1_state <= CAL1_DONE;
+ // stop when all DQ's calibrated, or DQ[0] cal'ed (for sim)
+ if ((count_dq == DQ_WIDTH-1) || (SIM_ONLY != 0))
+ calib_done_tmp[0] <= 1'b1;
+ else
+ // need for VHDL simulation to prevent out-of-index error
+ next_count_dq <= count_dq + 1;
+ end else begin
+ // keep decrementing until final tap count reached
+ cal1_idel_dec_cnt <= cal1_idel_dec_cnt - 1;
+ cal1_dlyce_dq <= 1'b1;
+ cal1_dlyinc_dq <= 1'b0;
+ end
+
+ // delay state to allow count_dq and DATA_CHK to point to the next
+ // DQ bit (allows us to potentially begin checking for an edge on
+ // next DQ right away).
+ CAL1_DONE:
+ if (!idel_set_wait) begin
+ count_dq <= next_count_dq;
+ if (calib_done_tmp[0]) begin
+ calib_done[0] <= 1'b1;
+ cal1_state <= CAL1_IDLE;
+ end else begin
+ // request auto-refresh after every 8-bits calibrated to
+ // avoid tRAS violation
+ if (cal1_refresh) begin
+ cal1_ref_req <= 1'b1;
+ if (calib_ref_done)
+ cal1_state <= CAL1_INIT;
+ end else
+ // if no need this time for refresh, proceed to next bit
+ cal1_state <= CAL1_INIT;
+ end
+ end
+ endcase
+ end
+
+ //***************************************************************************
+ // Second stage calibration: DQS-FPGA Clock
+ // Algorithm Description:
+ // 1. Assumes a training pattern that will produce a pattern oscillating at
+ // half the core clock frequency each on rise and fall outputs, and such
+ // that rise and fall outputs are 180 degrees out of phase from each
+ // other. Note that since the calibration logic runs at half the speed
+ // of the interface, expect that data sampled with the slow clock always
+ // to be constant (either always = 1, or = 0, and rise data != fall data)
+ // unless we cross the edge of the data valid window
+ // 2. Start by setting RD_DATA_SEL = 0. This selects the rising capture data
+ // sync'ed to rising edge of core clock, and falling edge data sync'ed
+ // to falling edge of core clock
+ // 3. Start looking for an edge. An edge is defined as either: (1) a
+ // change in capture value or (2) an invalid capture value (e.g. rising
+ // data != falling data for that same clock cycle).
+ // 4. If an edge is found, go to step (6). If edge hasn't been found, then
+ // set RD_DATA_SEL = 1, and try again.
+ // 5. If no edge is found, then increment IDELAY and return to step (3)
+ // 6. If an edge if found, then invert RD_DATA_SEL - this shifts the
+ // capture point 180 degrees from the edge of the window (minus duty
+ // cycle distortion, delay skew between rising/falling edge capture
+ // paths, etc.)
+ // 7. If no edge is found by CAL2_IDEL_TAP_LIMIT (= 63 - # taps used for
+ // stage 1 calibration), then decrement IDELAY (without reinverting
+ // RD_DATA_SEL) by CAL2_IDEL_TAP_LIMIT/2. This guarantees we at least
+ // have CAL2_IDEL_TAP_LIMIT/2 of slack both before and after the
+ // capture point (not optimal, but best we can do not having found an
+ // of the window). This happens only for very low frequencies.
+ // 8. Repeat for each DQS group.
+ // NOTE: Step 6 is not optimal. A better (and perhaps more complicated)
+ // algorithm might be to find both edges of the data valid window (using
+ // the same polarity of RD_DATA_SEL), and then decrement to the midpoint.
+ //***************************************************************************
+
+ // RD_DATA_SEL should be tagged with FROM-TO (multi-cycle) constraint in
+ // UCF file to relax timing. This net is "pseudo-static" (after value is
+ // changed, FSM waits number of cycles before using the output).
+ // Note that we are adding one clock cycle of delay (to isolate it from
+ // the other logic CAL2_RD_DATA_SEL feeds), make sure FSM waits long
+ // enough to compensate (by default it does, it waits a few cycles more
+ // than minimum # of clock cycles)
+ genvar rd_i;
+ generate
+ for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rd_data_sel
+ FDRSE u_ff_rd_data_sel
+ (
+ .Q (rd_data_sel[rd_i]),
+ .C (clkdiv),
+ .CE (1'b1),
+ .D (cal2_rd_data_sel[rd_i]),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ end
+ endgenerate
+
+ //*****************************************************************
+ // Max number of taps used for stg2 cal dependent on number of taps
+ // used for stg1 (give priority to stg1 cal - let it use as many
+ // taps as it needs - the remainder of the IDELAY taps can be used
+ // by stg2)
+ //*****************************************************************
+
+ always @(posedge clkdiv)
+ cal2_idel_tap_limit <= 6'b111111 - cal1_idel_max_tap;
+
+ //*****************************************************************
+ // second stage calibration uses readback pattern of "1100" (i.e.
+ // 1st rising = 1, 1st falling = 1, 2nd rising = 0, 2nd falling = 0)
+ // only look at the first bit of each DQS group
+ //*****************************************************************
+
+ // deasserted when captured data has changed since IDELAY was
+ // incremented, or when we're right on the edge (i.e. rise data =
+ // fall data).
+ assign cal2_detect_edge =
+ ((((rdd_rise_q1 != cal2_rd_data_rise_last_pos) ||
+ (rdd_fall_q1 != cal2_rd_data_fall_last_pos)) &&
+ cal2_rd_data_last_valid_pos && (!cal2_curr_sel)) ||
+ (((rdd_rise_q1 != cal2_rd_data_rise_last_neg) ||
+ (rdd_fall_q1 != cal2_rd_data_fall_last_neg)) &&
+ cal2_rd_data_last_valid_neg && (cal2_curr_sel)) ||
+ (rdd_rise_q1 != rdd_fall_q1));
+
+ //*****************************************************************
+ // keep track of edge tap counts found, and whether we've
+ // incremented to the maximum number of taps allowed
+ // NOTE: Assume stage 2 cal always increments the tap count (never
+ // decrements) when searching for edge of the data valid window
+ //*****************************************************************
+
+ always @(posedge clkdiv)
+ if (cal2_state == CAL2_INIT) begin
+ cal2_idel_tap_limit_hit <= 1'b0;
+ cal2_idel_tap_cnt <= 6'b000000;
+ end else if (cal2_dlyce_dqs) begin
+ cal2_idel_tap_cnt <= cal2_idel_tap_cnt + 1;
+ cal2_idel_tap_limit_hit <= (cal2_idel_tap_cnt ==
+ cal2_idel_tap_limit - 1);
+ end
+
+ //*****************************************************************
+
+ always @(posedge clkdiv)
+ if (rstdiv) begin
+ calib_done[1] <= 1'b0;
+ calib_done_tmp[1] <= 1'bx;
+ calib_err[1] <= 1'b0;
+ count_dqs <= 'b0;
+ next_count_dqs <= 'b0;
+ cal2_dlyce_dqs <= 1'b0;
+ cal2_dlyinc_dqs <= 1'b0;
+ cal2_idel_dec_cnt <= 6'bxxxxxx;
+ cal2_rd_data_last_valid_neg <= 1'bx;
+ cal2_rd_data_last_valid_pos <= 1'bx;
+ cal2_rd_data_sel <= 'b0;
+ cal2_ref_req <= 1'b0;
+ cal2_state <= CAL2_IDLE;
+ end else begin
+ cal2_ref_req <= 1'b0;
+ cal2_dlyce_dqs <= 1'b0;
+ cal2_dlyinc_dqs <= 1'b0;
+
+ case (cal2_state)
+ CAL2_IDLE: begin
+ count_dqs <= 'b0;
+ next_count_dqs <= 'b0;
+ if (calib_start[1]) begin
+ cal2_rd_data_sel <= {DQS_WIDTH{1'b0}};
+ calib_done[1] <= 1'b0;
+ calib_done_tmp[1] <= 1'b0;
+ cal2_state <= CAL2_INIT;
+ end
+ end
+
+ // Pass through this state every time we calibrate a new DQS group
+ CAL2_INIT: begin
+ cal2_curr_sel <= 1'b0;
+ cal2_rd_data_last_valid_neg <= 1'b0;
+ cal2_rd_data_last_valid_pos <= 1'b0;
+ cal2_state <= CAL2_INIT_IDEL_WAIT;
+ end
+
+ // Stall state only used if calibration run more than once. Can take
+ // this state out if design never runs calibration more than once.
+ // We need this state to give time for MUX'ed data to settle after
+ // resetting RD_DATA_SEL
+ CAL2_INIT_IDEL_WAIT:
+ if (!idel_set_wait)
+ cal2_state <= CAL2_FIND_EDGE_POS;
+
+ // Look for an edge - first check "positive-edge" stage 2 capture
+ CAL2_FIND_EDGE_POS: begin
+ // if found an edge, then switch to the opposite edge stage 2
+ // capture and we're done - no need to decrement the tap count,
+ // since switching to the opposite edge will shift the capture
+ // point by 180 degrees
+ if (cal2_detect_edge) begin
+ cal2_curr_sel <= 1'b1;
+ cal2_state <= CAL2_DONE;
+ // set all DQS groups to be the same for simulation
+ if (SIM_ONLY != 0)
+ cal2_rd_data_sel <= {DQS_WIDTH{1'b1}};
+ else
+ cal2_rd_data_sel[count_dqs] <= 1'b1;
+ if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
+ calib_done_tmp[1] <= 1'b1;
+ else
+ // MIG 2.1: Fix for simulation out-of-bounds error when
+ // SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
+ next_count_dqs <= count_dqs + 1;
+ end else begin
+ // otherwise, invert polarity of stage 2 capture and look for
+ // an edge with opposite capture clock polarity
+ cal2_curr_sel <= 1'b1;
+ cal2_rd_data_sel[count_dqs] <= 1'b1;
+ cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_POS;
+ cal2_rd_data_rise_last_pos <= rdd_rise_q1;
+ cal2_rd_data_fall_last_pos <= rdd_fall_q1;
+ cal2_rd_data_last_valid_pos <= 1'b1;
+ end
+ end
+
+ // Give time to switch from positive-edge to negative-edge second
+ // stage capture (need time for data to filter though pipe stages)
+ CAL2_FIND_EDGE_IDEL_WAIT_POS:
+ if (!idel_set_wait)
+ cal2_state <= CAL2_FIND_EDGE_NEG;
+
+ // Look for an edge - check "negative-edge" stage 2 capture
+ CAL2_FIND_EDGE_NEG:
+ if (cal2_detect_edge) begin
+ cal2_curr_sel <= 1'b0;
+ cal2_state <= CAL2_DONE;
+ // set all DQS groups to be the same for simulation
+ if (SIM_ONLY != 0)
+ cal2_rd_data_sel <= {DQS_WIDTH{1'b0}};
+ else
+ cal2_rd_data_sel[count_dqs] <= 1'b0;
+ if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
+ calib_done_tmp[1] <= 1'b1;
+ else
+ // MIG 2.1: Fix for simulation out-of-bounds error when
+ // SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
+ next_count_dqs <= count_dqs + 1;
+ end else if (cal2_idel_tap_limit_hit) begin
+ // otherwise, if we've run out of taps, then immediately
+ // backoff by half # of taps used - that's our best estimate
+ // for optimal calibration point. Doesn't matter whether which
+ // polarity we're using for capture (we don't know which one is
+ // best to use)
+ cal2_idel_dec_cnt <= {1'b0, cal2_idel_tap_limit[5:1]};
+ cal2_state <= CAL2_DEC_IDEL;
+ if ((count_dqs == DQS_WIDTH-1) || (SIM_ONLY != 0))
+ calib_done_tmp[1] <= 1'b1;
+ else
+ // MIG 2.1: Fix for simulation out-of-bounds error when
+ // SIM_ONLY=0, and DQS_WIDTH=(power of 2) (needed for VHDL)
+ next_count_dqs <= count_dqs + 1;
+ end else begin
+ // otherwise, increment IDELAY, and start looking for edge again
+ cal2_curr_sel <= 1'b0;
+ cal2_rd_data_sel[count_dqs] <= 1'b0;
+ cal2_state <= CAL2_FIND_EDGE_IDEL_WAIT_NEG;
+ cal2_rd_data_rise_last_neg <= rdd_rise_q1;
+ cal2_rd_data_fall_last_neg <= rdd_fall_q1;
+ cal2_rd_data_last_valid_neg <= 1'b1;
+ cal2_dlyce_dqs <= 1'b1;
+ cal2_dlyinc_dqs <= 1'b1;
+ end
+
+ CAL2_FIND_EDGE_IDEL_WAIT_NEG:
+ if (!idel_set_wait)
+ cal2_state <= CAL2_FIND_EDGE_POS;
+
+ // if no edge found, then decrement by half # of taps used
+ CAL2_DEC_IDEL: begin
+ if (cal2_idel_dec_cnt == 6'b000000)
+ cal2_state <= CAL2_DONE;
+ else begin
+ cal2_idel_dec_cnt <= cal2_idel_dec_cnt - 1;
+ cal2_dlyce_dqs <= 1'b1;
+ cal2_dlyinc_dqs <= 1'b0;
+ end
+ end
+
+ // delay state to allow count_dqs and ISERDES data to point to next
+ // DQ bit (DQS group) before going to INIT
+ CAL2_DONE:
+ if (!idel_set_wait) begin
+ count_dqs <= next_count_dqs;
+ if (calib_done_tmp[1]) begin
+ calib_done[1] <= 1'b1;
+ cal2_state <= CAL2_IDLE;
+ end else begin
+ // request auto-refresh after every DQS group calibrated to
+ // avoid tRAS violation
+ cal2_ref_req <= 1'b1;
+ if (calib_ref_done)
+ cal2_state <= CAL2_INIT;
+ end
+ end
+ endcase
+ end
+
+ //***************************************************************************
+ // Stage 3 calibration: Read Enable
+ // Description:
+ // read enable calibration determines the "round-trip" time (in # of CLK0
+ // cycles) between when a read command is issued by the controller, and
+ // when the corresponding read data is synchronized by into the CLK0 domain
+ // this is a long delay chain to delay read enable signal from controller/
+ // initialization logic (i.e. this is used for both initialization and
+ // during normal controller operation). Stage 3 calibration logic decides
+ // which delayed version is appropriate to use (which is affected by the
+ // round trip delay of DQ/DQS) as a "valid" signal to tell rest of logic
+ // when the captured data output from ISERDES is valid.
+ //***************************************************************************
+
+ //*****************************************************************
+ // Delay chains: Use shift registers
+ // Two sets of delay chains are used:
+ // 1. One to delay RDEN from PHY_INIT module for calibration
+ // purposes (delay required for RDEN for calibration is different
+ // than during normal operation)
+ // 2. One per DQS group to delay RDEN from controller for normal
+ // operation - the value to delay for each DQS group can be different
+ // as is determined during calibration
+ //*****************************************************************
+
+ //*****************************************************************
+ // First delay chain, use only for calibration
+ // input = asserted on rising edge of RDEN from PHY_INIT module
+ //*****************************************************************
+
+ always @(posedge clk) begin
+ ctrl_rden_r <= ctrl_rden;
+ phy_init_rden_r <= phy_init_rden;
+ phy_init_rden_r1 <= phy_init_rden_r;
+ calib_rden_edge_r <= phy_init_rden_r & ~phy_init_rden_r1;
+ end
+
+ // Calibration shift register used for both Stage 3 and Stage 4 cal
+ // (not strictly necessary for stage 4, but use as an additional check
+ // to make sure we're checking for correct data on the right clock cycle)
+ always @(posedge clkdiv)
+ if (!calib_done[2])
+ calib_rden_srl_a <= cal3_rden_srl_a;
+ else
+ calib_rden_srl_a <= cal4_rden_srl_a;
+
+ // Flops for targetting of multi-cycle path in UCF
+ genvar cal_rden_ff_i;
+ generate
+ for (cal_rden_ff_i = 0; cal_rden_ff_i < 5;
+ cal_rden_ff_i = cal_rden_ff_i+1) begin: gen_cal_rden_dly
+ FDRSE u_ff_cal_rden_dly
+ (
+ .Q (calib_rden_srl_a_r[cal_rden_ff_i]),
+ .C (clkdiv),
+ .CE (1'b1),
+ .D (calib_rden_srl_a[cal_rden_ff_i]),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ end
+ endgenerate
+
+ SRLC32E u_calib_rden_srl
+ (
+ .Q (calib_rden_srl_out),
+ .Q31 (),
+ .A (calib_rden_srl_a_r),
+ .CE (1'b1),
+ .CLK (clk),
+ .D (calib_rden_edge_r)
+ );
+
+ FDRSE u_calib_rden_srl_out_r
+ (
+ .Q (calib_rden_srl_out_r),
+ .C (clk),
+ .CE (1'b1),
+ .D (calib_rden_srl_out),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve = 1 */;
+
+ // convert to CLKDIV domain. Two version are generated because we need
+ // to be able to tell exactly which fast (clk) clock cycle the read
+ // enable was asserted in. Only one of CALIB_DATA_VALID or
+ // CALIB_DATA_VALID_STGD will be asserted for any given shift value
+ always @(posedge clk)
+ calib_rden_srl_out_r1 <= calib_rden_srl_out_r;
+
+ always @(posedge clkdiv) begin
+ calib_rden_valid <= calib_rden_srl_out_r;
+ calib_rden_valid_stgd <= calib_rden_srl_out_r1;
+ end
+
+ //*****************************************************************
+ // Second set of delays chain, use for normal reads
+ // input = RDEN from controller
+ //*****************************************************************
+
+ // Flops for targetting of multi-cycle path in UCF
+ genvar rden_ff_i;
+ generate
+ for (rden_ff_i = 0; rden_ff_i < 5*DQS_WIDTH;
+ rden_ff_i = rden_ff_i+1) begin: gen_rden_dly
+ FDRSE u_ff_rden_dly
+ (
+ .Q (rden_dly_r[rden_ff_i]),
+ .C (clkdiv),
+ .CE (1'b1),
+ .D (rden_dly[rden_ff_i]),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ end
+ endgenerate
+
+ // NOTE: Comment this section explaining purpose of SRL's
+ genvar rden_i;
+ generate
+ for (rden_i = 0; rden_i < DQS_WIDTH; rden_i = rden_i + 1) begin: gen_rden
+ SRLC32E u_rden_srl
+ (
+ .Q (rden_srl_out[rden_i]),
+ .Q31 (),
+ .A ({rden_dly_r[(rden_i*5)+4],
+ rden_dly_r[(rden_i*5)+3],
+ rden_dly_r[(rden_i*5)+2],
+ rden_dly_r[(rden_i*5)+1],
+ rden_dly_r[(rden_i*5)]}),
+ .CE (1'b1),
+ .CLK (clk),
+ .D (ctrl_rden_r)
+ );
+ FDRSE u_calib_rden_r
+ (
+ .Q (calib_rden[rden_i]),
+ .C (clk),
+ .CE (1'b1),
+ .D (rden_srl_out[rden_i]),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve = 1 */;
+ end
+ endgenerate
+
+ //*****************************************************************
+ // indicates that current received data is the correct pattern. Check both
+ // rising and falling data for first DQ in each DQS group. Note that
+ // we're checking using a pipelined version of read data, so need to take
+ // this inherent delay into account in determining final read valid delay
+ // Data is written to the memory in the following order (first -> last):
+ // 0x1, 0xE, 0xE, 0x1, 0x1, 0xE, 0x1, 0xE
+ // Looking at the two LSb bits, expect data in sequence (in binary):
+ // bit[0]: 1, 0, 0, 1, 0, 1, 0, 1
+ // bit[1]: 0, 1, 1, 0, 1, 0, 1, 0
+ // Check for the presence of the first 7 words, and compensate read valid
+ // delay accordingly. Don't check last falling edge data, it may be
+ // corrupted by the DQS tri-state glitch at end of read postamble
+ // (glitch protection not yet active until stage 4 cal)
+ //*****************************************************************
+
+ always @(posedge clkdiv) begin
+ rdd_rise_q1_r <= rdd_rise_q1;
+ rdd_fall_q1_r <= rdd_fall_q1;
+ rdd_rise_q2_r <= rdd_rise_q2;
+ rdd_fall_q2_r <= rdd_fall_q2;
+ rdd_rise_q1_r1 <= rdd_rise_q1_r;
+ rdd_fall_q1_r1 <= rdd_fall_q1_r;
+ // MIG 3.3: Added comparison for second bit in DQS group for stage 3 cal
+ rdd_rise_q1_bit1_r <= rdd_rise_q1_bit1;
+ rdd_fall_q1_bit1_r <= rdd_fall_q1_bit1;
+ rdd_rise_q2_bit1_r <= rdd_rise_q2_bit1;
+ rdd_fall_q2_bit1_r <= rdd_fall_q2_bit1;
+ rdd_rise_q1_bit1_r1 <= rdd_rise_q1_bit1_r;
+ rdd_fall_q1_bit1_r1 <= rdd_fall_q1_bit1_r;
+ end
+
+ always @(posedge clkdiv) begin
+ // For the following sequence from memory:
+ // rise[0], fall[0], rise[1], fall[1]
+ // if data is aligned out of fabric ISERDES:
+ // RDD_RISE_Q2 = rise[0]
+ // RDD_FALL_Q2 = fall[0]
+ // RDD_RISE_Q1 = rise[1]
+ // RDD_FALL_Q1 = fall[1]
+ cal3_data_match <= ((rdd_rise_q2_r == 1) &&
+ (rdd_fall_q2_r == 0) &&
+ (rdd_rise_q1_r == 0) &&
+ (rdd_fall_q1_r == 1) &&
+ (rdd_rise_q2 == 0) &&
+ (rdd_fall_q2 == 1) &&
+ (rdd_rise_q1 == 0) &&
+ (rdd_rise_q2_bit1_r == 0) &&
+ (rdd_fall_q2_bit1_r == 1) &&
+ (rdd_rise_q1_bit1_r == 1) &&
+ (rdd_fall_q1_bit1_r == 0) &&
+ (rdd_rise_q2_bit1 == 1) &&
+ (rdd_fall_q2_bit1 == 0) &&
+ (rdd_rise_q1_bit1 == 1));
+
+ // if data is staggered out of fabric ISERDES:
+ // RDD_RISE_Q1_R = rise[0]
+ // RDD_FALL_Q1_R = fall[0]
+ // RDD_RISE_Q2 = rise[1]
+ // RDD_FALL_Q2 = fall[1]
+ cal3_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
+ (rdd_fall_q1_r1 == 0) &&
+ (rdd_rise_q2_r == 0) &&
+ (rdd_fall_q2_r == 1) &&
+ (rdd_rise_q1_r == 0) &&
+ (rdd_fall_q1_r == 1) &&
+ (rdd_rise_q2 == 0) &&
+ (rdd_rise_q1_bit1_r1 == 0) &&
+ (rdd_fall_q1_bit1_r1 == 1) &&
+ (rdd_rise_q2_bit1_r == 1) &&
+ (rdd_fall_q2_bit1_r == 0) &&
+ (rdd_rise_q1_bit1_r == 1) &&
+ (rdd_fall_q1_bit1_r == 0) &&
+ (rdd_rise_q2_bit1 == 1));
+ end
+
+ assign cal3_rden_dly = cal3_rden_srl_a - CAL3_RDEN_SRL_DLY_DELTA;
+ assign cal3_data_valid = (calib_rden_valid | calib_rden_valid_stgd);
+ assign cal3_match_found
+ = ((calib_rden_valid && cal3_data_match) ||
+ (calib_rden_valid_stgd && cal3_data_match_stgd));
+
+ // when calibrating, check to see which clock cycle (after the read is
+ // issued) does the expected data pattern arrive. Record this result
+ // NOTE: Can add error checking here in case valid data not found on any
+ // of the available pipeline stages
+ always @(posedge clkdiv) begin
+ if (rstdiv) begin
+ cal3_rden_srl_a <= 5'bxxxxx;
+ cal3_state <= CAL3_IDLE;
+ calib_done[2] <= 1'b0;
+ calib_err_2[0] <= 1'b0;
+ count_rden <= {DQS_WIDTH{1'b0}};
+ rden_dly <= {5*DQS_WIDTH{1'b0}};
+ end else begin
+
+ case (cal3_state)
+ CAL3_IDLE: begin
+ count_rden <= {DQS_WIDTH{1'b0}};
+ if (calib_start[2]) begin
+ calib_done[2] <= 1'b0;
+ cal3_state <= CAL3_INIT;
+ end
+ end
+
+ CAL3_INIT: begin
+ cal3_rden_srl_a <= RDEN_BASE_DELAY;
+ // let SRL pipe clear after loading initial shift value
+ cal3_state <= CAL3_RDEN_PIPE_CLR_WAIT;
+ end
+
+ CAL3_DETECT:
+ if (cal3_data_valid)
+ // if match found at the correct clock cycle
+ if (cal3_match_found) begin
+
+ // For simulation, load SRL addresses for all DQS with same value
+ if (SIM_ONLY != 0) begin
+ for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_rden_dly
+ rden_dly[(i*5)] <= cal3_rden_dly[0];
+ rden_dly[(i*5)+1] <= cal3_rden_dly[1];
+ rden_dly[(i*5)+2] <= cal3_rden_dly[2];
+ rden_dly[(i*5)+3] <= cal3_rden_dly[3];
+ rden_dly[(i*5)+4] <= cal3_rden_dly[4];
+ end
+ end else begin
+ rden_dly[(count_rden*5)] <= cal3_rden_dly[0];
+ rden_dly[(count_rden*5)+1] <= cal3_rden_dly[1];
+ rden_dly[(count_rden*5)+2] <= cal3_rden_dly[2];
+ rden_dly[(count_rden*5)+3] <= cal3_rden_dly[3];
+ rden_dly[(count_rden*5)+4] <= cal3_rden_dly[4];
+ end
+
+ // Use for stage 4 calibration
+ calib_rden_dly[(count_rden*5)] <= cal3_rden_srl_a[0];
+ calib_rden_dly[(count_rden*5)+1] <= cal3_rden_srl_a[1];
+ calib_rden_dly[(count_rden*5)+2] <= cal3_rden_srl_a[2];
+ calib_rden_dly[(count_rden*5)+3] <= cal3_rden_srl_a[3];
+ calib_rden_dly[(count_rden*5)+4] <= cal3_rden_srl_a[4];
+ cal3_state <= CAL3_DONE;
+ end else begin
+ // If we run out of stages to shift, without finding correct
+ // result, the stop and assert error
+ if (cal3_rden_srl_a == 5'b11111) begin
+ calib_err_2[0] <= 1'b1;
+ cal3_state <= CAL3_IDLE;
+ end else begin
+ // otherwise, increase the shift value and try again
+ cal3_rden_srl_a <= cal3_rden_srl_a + 1;
+ cal3_state <= CAL3_RDEN_PIPE_CLR_WAIT;
+ end
+ end
+
+ // give additional time for RDEN_R pipe to clear from effects of
+ // previous pipeline or IDELAY tap change
+ CAL3_RDEN_PIPE_CLR_WAIT:
+ if (calib_rden_pipe_cnt == 5'b00000)
+ cal3_state <= CAL3_DETECT;
+
+ CAL3_DONE: begin
+ if ((count_rden == DQS_WIDTH-1) || (SIM_ONLY != 0)) begin
+ calib_done[2] <= 1'b1;
+ cal3_state <= CAL3_IDLE;
+ end else begin
+ count_rden <= count_rden + 1;
+ cal3_state <= CAL3_INIT;
+ end
+ end
+ endcase
+ end
+ end
+
+ //*****************************************************************
+ // Last part of stage 3 calibration - compensate for differences
+ // in delay between different DQS groups. Assume that in the worst
+ // case, DQS groups can only differ by one clock cycle. Data for
+ // certain DQS groups must be delayed by one clock cycle.
+ // NOTE: May need to increase allowable variation to greater than
+ // one clock cycle in certain customer designs.
+ // Algorithm is:
+ // 1. Record shift delay value for DQS[0]
+ // 2. Compare each DQS[x] delay value to that of DQS[0]:
+ // - If different, than record this fact (RDEN_MUX)
+ // - If greater than DQS[0], set RDEN_INC. Assume greater by
+ // one clock cycle only - this is a key assumption, assume no
+ // more than a one clock cycle variation.
+ // - If less than DQS[0], set RDEN_DEC
+ // 3. After calibration is complete, set control for DQS group
+ // delay (CALIB_RDEN_SEL):
+ // - If RDEN_DEC = 1, then assume that DQS[0] is the lowest
+ // delay (and at least one other DQS group has a higher
+ // delay).
+ // - If RDEN_INC = 1, then assume that DQS[0] is the highest
+ // delay (and that all other DQS groups have the same or
+ // lower delay).
+ // - If both RDEN_INC and RDEN_DEC = 1, then flag error
+ // (variation is too high for this algorithm to handle)
+ //*****************************************************************
+
+ always @(posedge clkdiv) begin
+ if (rstdiv) begin
+ calib_err_2[1] <= 1'b0;
+ calib_rden_sel <= {DQS_WIDTH{1'bx}};
+ rden_dec <= 1'b0;
+ rden_dly_0 <= 5'bxxxxx;
+ rden_inc <= 1'b0;
+ rden_mux <= {DQS_WIDTH{1'b0}};
+ end else begin
+ // if a match if found, then store the value of rden_dly
+ if (!calib_done[2]) begin
+ if ((cal3_state == CAL3_DETECT) && cal3_match_found) begin
+ // store the value for DQS[0] as a reference
+ if (count_rden == 0) begin
+ // for simulation, RDEN calibration only happens for DQS[0]
+ // set RDEN_MUX for all DQS groups to be the same as DQS[0]
+ if (SIM_ONLY != 0)
+ rden_mux <= {DQS_WIDTH{1'b0}};
+ else begin
+ // otherwise, load values for DQS[0]
+ rden_dly_0 <= cal3_rden_srl_a;
+ rden_mux[0] <= 1'b0;
+ end
+ end else if (SIM_ONLY == 0) begin
+ // for all other DQS groups, compare RDEN_DLY delay value with
+ // that of DQS[0]
+ if (rden_dly_0 != cal3_rden_srl_a) begin
+ // record that current DQS group has a different delay
+ // than DQS[0] (the "reference" DQS group)
+ rden_mux[count_rden] <= 1'b1;
+ if (rden_dly_0 > cal3_rden_srl_a)
+ rden_inc <= 1'b1;
+ else if (rden_dly_0 < cal3_rden_srl_a)
+ rden_dec <= 1'b1;
+ // otherwise, if current DQS group has same delay as DQS[0],
+ // then rden_mux[count_rden] remains at 0 (since rden_mux
+ // array contents initialized to 0)
+ end
+ end
+ end
+ end else begin
+ // Otherwise - if we're done w/ stage 2 calibration:
+ // set final value for RDEN data delay
+ // flag error if there's more than one cycle variation from DQS[0]
+ calib_err_2[1] <= (rden_inc && rden_dec);
+ if (rden_inc)
+ // if DQS[0] delay represents max delay
+ calib_rden_sel <= ~rden_mux;
+ else
+ // if DQS[0] delay represents min delay (or all the delays are
+ // the same between DQS groups)
+ calib_rden_sel <= rden_mux;
+ end
+ end
+ end
+
+ // flag error for stage 3 if appropriate
+ always @(posedge clkdiv)
+ calib_err[2] <= calib_err_2[0] | calib_err_2[1];
+
+ //***************************************************************************
+ // Stage 4 calibration: DQS gate
+ //***************************************************************************
+
+ //*****************************************************************
+ // indicates that current received data is the correct pattern. Same as
+ // for READ VALID calibration, except that the expected data sequence is
+ // different since DQS gate is asserted after the 6th word.
+ // Data sequence:
+ // Arrives from memory (at FPGA input) (R, F): 1 0 0 1 1 0 0 1
+ // After gating the sequence looks like: 1 0 0 1 1 0 1 0 (7th word =
+ // 5th word, 8th word = 6th word)
+ // What is the gate timing is off? Need to make sure we can distinquish
+ // between the results of correct vs. incorrect gate timing. We also use
+ // the "read_valid" signal from stage 3 calibration to help us determine
+ // when to check for a valid sequence for stage 4 calibration (i.e. use
+ // CAL4_DATA_VALID in addition to CAL4_DATA_MATCH/CAL4_DATA_MATCH_STGD)
+ // Note that since the gate signal from the CLK0 domain is synchronized
+ // to the falling edge of DQS, that the effect of the gate will only be
+ // seen starting with a rising edge data (although it is possible
+ // the GATE IDDR output could go metastable and cause a unexpected result
+ // on the first rising and falling edges after the gate is enabled).
+ // Also note that the actual DQS glitch can come more than 0.5*tCK after
+ // the last falling edge of DQS and the constraint for this path is can
+ // be > 0.5*tCK; however, this means when calibrating, the output of the
+ // GATE IDDR may miss the setup time requirement of the rising edge flop
+ // and only meet it for the falling edge flop. Therefore the rising
+ // edge data immediately following the assertion of the gate can either
+ // be a 1 or 0 (can rely on either)
+ // As the timing on the gate is varied, we expect to see (sequence of
+ // captured read data shown below):
+ // - 1 0 0 1 1 0 0 1 (gate is really early, starts and ends before
+ // read burst even starts)
+ // - x 0 0 1 1 0 0 1 (gate pulse starts before the burst, and ends
+ // - x y 0 1 1 0 0 1 sometime during the burst; x,y = 0, or 1, but
+ // - x y x 1 1 0 0 1 all bits that show an x are the same value,
+ // - x y x y 1 0 0 1 and y are the same value)
+ // - x y x y x 0 0 1
+ // - x y x y x y 0 1 (gate starts just before start of burst)
+ // - 1 0 x 0 x 0 x 0 (gate starts after 1st falling word. The "x"
+ // represents possiblity that gate may not disable
+ // clock for 2nd rising word in time)
+ // - 1 0 0 1 x 1 x 1 (gate starts after 2nd falling word)
+ // - 1 0 0 1 1 0 x 0 (gate starts after 3rd falling word - GOOD!!)
+ // - 1 0 0 1 1 0 0 1 (gate starts after burst is already done)
+ //*****************************************************************
+
+ assign cal4_data_valid = calib_rden_valid | calib_rden_valid_stgd;
+ assign cal4_data_good = (calib_rden_valid &
+ cal4_data_match) |
+ (calib_rden_valid_stgd &
+ cal4_data_match_stgd);
+
+ always @(posedge clkdiv) begin
+ // if data is aligned out of fabric ISERDES:
+ cal4_data_match <= ((rdd_rise_q2_r == 1) &&
+ (rdd_fall_q2_r == 0) &&
+ (rdd_rise_q1_r == 0) &&
+ (rdd_fall_q1_r == 1) &&
+ (rdd_rise_q2 == 1) &&
+ (rdd_fall_q2 == 0) &&
+ // MIG 2.1: Last rising edge data value not
+ // guaranteed to be certain value at higher
+ // frequencies
+ // (rdd_rise_q1 == 0) &&
+ (rdd_fall_q1 == 0));
+ // if data is staggered out of fabric ISERDES:
+ cal4_data_match_stgd <= ((rdd_rise_q1_r1 == 1) &&
+ (rdd_fall_q1_r1 == 0) &&
+ (rdd_rise_q2_r == 0) &&
+ (rdd_fall_q2_r == 1) &&
+ (rdd_rise_q1_r == 1) &&
+ (rdd_fall_q1_r == 0) &&
+ // MIG 2.1: Last rising edge data value not
+ // guaranteed to be certain value at higher
+ // frequencies
+ // (rdd_rise_q2 == 0) &&
+ (rdd_fall_q2 == 0));
+ end
+
+ //*****************************************************************
+ // DQS gate enable generation:
+ // This signal gets synchronized to DQS domain, and drives IDDR
+ // register that in turn asserts/deasserts CE to all 4 or 8 DQ
+ // IDDR's in that DQS group.
+ // 1. During normal (post-cal) operation, this is only for 2 clock
+ // cycles following the end of a burst. Check for falling edge
+ // of RDEN. But must also make sure NOT assert for a read-idle-
+ // read (two non-consecutive reads, separated by exactly one
+ // idle cycle) - in this case, don't assert the gate because:
+ // (1) we don't have enough time to deassert the gate before the
+ // first rising edge of DQS for second burst (b/c of fact
+ // that DQS gate is generated in the fabric only off rising
+ // edge of CLK0 - if we somehow had an ODDR in fabric, we
+ // could pull this off, (2) assumption is that the DQS glitch
+ // will not rise enough to cause a glitch because the
+ // post-amble of the first burst is followed immediately by
+ // the pre-amble of the next burst
+ // 2. During stage 4 calibration, assert for 3 clock cycles
+ // (assert gate enable one clock cycle early), since we gate out
+ // the last two words (in addition to the crap on the DQ bus after
+ // the DQS read postamble).
+ // NOTE: PHY_INIT_RDEN and CTRL_RDEN have slightly different timing w/r
+ // to when they are asserted w/r to the start of the read burst
+ // (PHY_INIT_RDEN is one cycle earlier than CTRL_RDEN).
+ //*****************************************************************
+
+ // register for timing purposes for fast clock path - currently only
+ // calib_done_r[2] used
+ always @(posedge clk)
+ calib_done_r <= calib_done;
+
+ always @(*) begin
+ calib_ctrl_rden = ctrl_rden;
+ calib_init_rden = calib_done_r[2] & phy_init_rden;
+ end
+
+ assign calib_ctrl_rden_negedge = ~calib_ctrl_rden & calib_ctrl_rden_r;
+ // check for read-idle-read before asserting DQS pulse at end of read
+ assign calib_ctrl_gate_pulse = calib_ctrl_rden_negedge_r &
+ ~calib_ctrl_rden;
+ always @(posedge clk) begin
+ calib_ctrl_rden_r <= calib_ctrl_rden;
+ calib_ctrl_rden_negedge_r <= calib_ctrl_rden_negedge;
+ calib_ctrl_gate_pulse_r <= calib_ctrl_gate_pulse;
+ end
+
+ assign calib_init_gate_pulse = ~calib_init_rden & calib_init_rden_r;
+ always @(posedge clk) begin
+ calib_init_rden_r <= calib_init_rden;
+ calib_init_gate_pulse_r <= calib_init_gate_pulse;
+ calib_init_gate_pulse_r1 <= calib_init_gate_pulse_r;
+ end
+
+ // Gate is asserted: (1) during cal, for 3 cycles, starting 1 cycle
+ // after falling edge of CTRL_RDEN, (2) during normal ops, for 2
+ // cycles, starting 2 cycles after falling edge of CTRL_RDEN
+ assign gate_srl_in = ~((calib_ctrl_gate_pulse |
+ calib_ctrl_gate_pulse_r) |
+ (calib_init_gate_pulse |
+ calib_init_gate_pulse_r |
+ calib_init_gate_pulse_r1));
+
+ //*****************************************************************
+ // generate DQS enable signal for each DQS group
+ // There are differences between DQS gate signal for calibration vs. during
+ // normal operation:
+ // * calibration gates the second to last clock cycle of the burst,
+ // rather than after the last word (e.g. for a 8-word, 4-cycle burst,
+ // cycle 4 is gated for calibration; during normal operation, cycle
+ // 5 (i.e. cycle after the last word) is gated)
+ // enable for DQS is deasserted for two clock cycles, except when
+ // we have the preamble for the next read immediately following
+ // the postamble of the current read - assume DQS does not glitch
+ // during this time, that it stays low. Also if we did have to gate
+ // the DQS for this case, then we don't have enough time to deassert
+ // the gate in time for the first rising edge of DQS for the second
+ // read
+ //*****************************************************************
+
+ // Flops for targetting of multi-cycle path in UCF
+ genvar gate_ff_i;
+ generate
+ for (gate_ff_i = 0; gate_ff_i < 5*DQS_WIDTH;
+ gate_ff_i = gate_ff_i+1) begin: gen_gate_dly
+ FDRSE u_ff_gate_dly
+ (
+ .Q (gate_dly_r[gate_ff_i]),
+ .C (clkdiv),
+ .CE (1'b1),
+ .D (gate_dly[gate_ff_i]),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ end
+ endgenerate
+
+ genvar gate_i;
+ generate
+ for (gate_i = 0; gate_i < DQS_WIDTH; gate_i = gate_i + 1) begin: gen_gate
+ SRLC32E u_gate_srl
+ (
+ .Q (gate_srl_out[gate_i]),
+ .Q31 (),
+ .A ({gate_dly_r[(gate_i*5)+4],
+ gate_dly_r[(gate_i*5)+3],
+ gate_dly_r[(gate_i*5)+2],
+ gate_dly_r[(gate_i*5)+1],
+ gate_dly_r[(gate_i*5)]}),
+ .CE (1'b1),
+ .CLK (clk),
+ .D (gate_srl_in)
+ );
+
+ // For GATE_BASE_DELAY > 0, have one extra cycle to register outputs
+ // from controller before generating DQS gate pulse. In PAR, the
+ // location of the controller logic can be far from the DQS gate
+ // logic (DQS gate logic located near the DQS I/O's), contributing
+ // to large net delays. Registering the controller outputs for
+ // CL >= 4 (above 200MHz) adds a stage of pipelining to reduce net
+ // delays
+ if (GATE_BASE_DELAY > 0) begin: gen_gate_base_dly_gt3
+ // add flop between SRL32 and EN_DQS flop (which is located near the
+ // DDR2 IOB's)
+ FDRSE u_gate_srl_ff
+ (
+ .Q (gate_srl_out_r[gate_i]),
+ .C (clk),
+ .CE (1'b1),
+ .D (gate_srl_out[gate_i]),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve = 1 */;
+ end else begin: gen_gate_base_dly_le3
+ assign gate_srl_out_r[gate_i] = gate_srl_out[gate_i];
+ end
+
+ FDRSE u_en_dqs_ff
+ (
+ .Q (en_dqs[gate_i]),
+ .C (clk),
+ .CE (1'b1),
+ .D (gate_srl_out_r[gate_i]),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve = 1 */
+ /* synthesis syn_replicate = 0 */;
+ end
+ endgenerate
+
+ //*****************************************************************
+ // Find valid window: keep track of how long we've been in the same data
+ // window. If it's been long enough, then declare that we've found a stable
+ // valid window - in particular, that we're past any region of instability
+ // associated with the edge of the window. Use only when finding left edge
+ //*****************************************************************
+
+ always @(posedge clkdiv)
+ // reset before we start to look for window
+ if (cal4_state == CAL4_INIT) begin
+ cal4_window_cnt <= 4'b0000;
+ cal4_stable_window <= 1'b0;
+ end else if ((cal4_state == CAL4_FIND_EDGE) && cal4_seek_left) begin
+ // if we're looking for left edge, and incrementing IDELAY, count
+ // consecutive taps over which we're in the window
+ if (cal4_data_valid) begin
+ if (cal4_data_good)
+ cal4_window_cnt <= cal4_window_cnt + 1;
+ else
+ cal4_window_cnt <= 4'b0000;
+ end
+
+ if (cal4_window_cnt == MIN_WIN_SIZE-1)
+ cal4_stable_window <= 1'b1;
+ end
+
+ //*****************************************************************
+ // keep track of edge tap counts found, and whether we've
+ // incremented to the maximum number of taps allowed
+ //*****************************************************************
+
+ always @(posedge clkdiv)
+ if ((cal4_state == CAL4_INIT) || cal4_dlyrst_gate) begin
+ cal4_idel_max_tap <= 1'b0;
+ cal4_idel_bit_tap <= 1'b0;
+ cal4_idel_tap_cnt <= 6'b000000;
+ end else if (cal4_dlyce_gate) begin
+ if (cal4_dlyinc_gate) begin
+ cal4_idel_tap_cnt <= cal4_idel_tap_cnt + 1;
+ cal4_idel_bit_tap <= (cal4_idel_tap_cnt == CAL4_IDEL_BIT_VAL-2);
+ cal4_idel_max_tap <= (cal4_idel_tap_cnt == 6'b111110);
+ end else begin
+ cal4_idel_tap_cnt <= cal4_idel_tap_cnt - 1;
+ cal4_idel_bit_tap <= 1'b0;
+ cal4_idel_max_tap <= 1'b0;
+ end
+ end
+
+ always @(posedge clkdiv)
+ if ((cal4_state != CAL4_RDEN_PIPE_CLR_WAIT) &&
+ (cal3_state != CAL3_RDEN_PIPE_CLR_WAIT))
+ calib_rden_pipe_cnt <= CALIB_RDEN_PIPE_LEN-1;
+ else
+ calib_rden_pipe_cnt <= calib_rden_pipe_cnt - 1;
+
+ //*****************************************************************
+ // Stage 4 cal state machine
+ //*****************************************************************
+
+ always @(posedge clkdiv)
+ if (rstdiv) begin
+ calib_done[3] <= 1'b0;
+ calib_done_tmp[3] <= 1'b0;
+ calib_err[3] <= 1'b0;
+ count_gate <= 'b0;
+ gate_dly <= 'b0;
+ next_count_gate <= 'b0;
+ cal4_idel_adj_cnt <= 6'bxxxxxx;
+ cal4_dlyce_gate <= 1'b0;
+ cal4_dlyinc_gate <= 1'b0;
+ cal4_dlyrst_gate <= 1'b0; // reset handled elsewhere in code
+ cal4_gate_srl_a <= 5'bxxxxx;
+ cal4_rden_srl_a <= 5'bxxxxx;
+ cal4_ref_req <= 1'b0;
+ cal4_seek_left <= 1'bx;
+ cal4_state <= CAL4_IDLE;
+ end else begin
+ cal4_ref_req <= 1'b0;
+ cal4_dlyce_gate <= 1'b0;
+ cal4_dlyinc_gate <= 1'b0;
+ cal4_dlyrst_gate <= 1'b0;
+
+ case (cal4_state)
+ CAL4_IDLE: begin
+ count_gate <= 'b0;
+ next_count_gate <= 'b0;
+ if (calib_start[3]) begin
+ gate_dly <= 'b0;
+ calib_done[3] <= 1'b0;
+ cal4_state <= CAL4_INIT;
+ end
+ end
+
+ CAL4_INIT: begin
+ // load: (1) initial value of gate delay SRL, (2) appropriate
+ // value of RDEN SRL (so that we get correct "data valid" timing)
+ cal4_gate_srl_a <= GATE_BASE_INIT;
+ cal4_rden_srl_a <= {calib_rden_dly[(count_gate*5)+4],
+ calib_rden_dly[(count_gate*5)+3],
+ calib_rden_dly[(count_gate*5)+2],
+ calib_rden_dly[(count_gate*5)+1],
+ calib_rden_dly[(count_gate*5)]};
+ // let SRL pipe clear after loading initial shift value
+ cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
+ end
+
+ // sort of an initial state - start checking to see whether we're
+ // already in the window or not
+ CAL4_FIND_WINDOW:
+ // decide right away if we start in the proper window - this
+ // determines if we are then looking for the left (trailing) or
+ // right (leading) edge of the data valid window
+ if (cal4_data_valid) begin
+ // if we find a match - then we're already in window, now look
+ // for left edge. Otherwise, look for right edge of window
+ cal4_seek_left <= cal4_data_good;
+ cal4_state <= CAL4_FIND_EDGE;
+ end
+
+ CAL4_FIND_EDGE:
+ // don't do anything until the exact clock cycle when to check that
+ // readback data is valid or not
+ if (cal4_data_valid) begin
+ // we're currently in the window, look for left edge of window
+ if (cal4_seek_left) begin
+ // make sure we've passed the right edge before trying to detect
+ // the left edge (i.e. avoid any edge "instability") - else, we
+ // may detect an "false" edge too soon. By design, if we start in
+ // the data valid window, always expect at least
+ // MIN(BIT_TIME_TAPS,32) (-/+ jitter, see below) taps of valid
+ // window before we hit the left edge (this is because when stage
+ // 4 calibration first begins (i.e., gate_dly = 00, and IDELAY =
+ // 00), we're guaranteed to NOT be in the window, and we always
+ // start searching for MIN(BIT_TIME_TAPS,32) for the right edge
+ // of window. If we don't find it, increment gate_dly, and if we
+ // now start in the window, we have at least approximately
+ // CLK_PERIOD-MIN(BIT_TIME_TAPS,32) = MIN(BIT_TIME_TAPS,32) taps.
+ // It's approximately because jitter, noise, etc. can bring this
+ // value down slightly. Because of this (although VERY UNLIKELY),
+ // we have to protect against not decrementing IDELAY below 0
+ // during adjustment phase).
+ if (cal4_stable_window && !cal4_data_good) begin
+ // found left edge of window, dec by MIN(BIT_TIME_TAPS,32)
+ cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
+ cal4_idel_adj_inc <= 1'b0;
+ cal4_state <= CAL4_ADJ_IDEL;
+ end else begin
+ // Otherwise, keep looking for left edge:
+ if (cal4_idel_max_tap) begin
+ // ran out of taps looking for left edge (max=63) - happens
+ // for low frequency case, decrement by 32
+ cal4_idel_adj_cnt <= 6'b100000;
+ cal4_idel_adj_inc <= 1'b0;
+ cal4_state <= CAL4_ADJ_IDEL;
+ end else begin
+ cal4_dlyce_gate <= 1'b1;
+ cal4_dlyinc_gate <= 1'b1;
+ cal4_state <= CAL4_IDEL_WAIT;
+ end
+ end
+ end else begin
+ // looking for right edge of window:
+ // look for the first match - this means we've found the right
+ // (leading) edge of the data valid window, increment by
+ // MIN(BIT_TIME_TAPS,32)
+ if (cal4_data_good) begin
+ cal4_idel_adj_cnt <= CAL4_IDEL_BIT_VAL;
+ cal4_idel_adj_inc <= 1'b1;
+ cal4_state <= CAL4_ADJ_IDEL;
+ end else begin
+ // Otherwise, keep looking:
+ // only look for MIN(BIT_TIME_TAPS,32) taps for right edge,
+ // if we haven't found it, then inc gate delay, try again
+ if (cal4_idel_bit_tap) begin
+ // if we're already maxed out on gate delay, then error out
+ // (simulation only - calib_err isn't currently connected)
+ if (cal4_gate_srl_a == 5'b11111) begin
+ calib_err[3] <= 1'b1;
+ cal4_state <= CAL4_IDLE;
+ end else begin
+ // otherwise, increment gate delay count, and start
+ // over again
+ cal4_gate_srl_a <= cal4_gate_srl_a + 1;
+ cal4_dlyrst_gate <= 1'b1;
+ cal4_state <= CAL4_RDEN_PIPE_CLR_WAIT;
+ end
+ end else begin
+ // keep looking for right edge
+ cal4_dlyce_gate <= 1'b1;
+ cal4_dlyinc_gate <= 1'b1;
+ cal4_state <= CAL4_IDEL_WAIT;
+ end
+ end
+ end
+ end
+
+ // wait for GATE IDELAY to settle, after reset or increment
+ CAL4_IDEL_WAIT: begin
+ // For simulation, load SRL addresses for all DQS with same value
+ if (SIM_ONLY != 0) begin
+ for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly
+ gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
+ gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
+ gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
+ gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
+ gate_dly[(i*5)] <= cal4_gate_srl_a[0];
+ end
+ end else begin
+ gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
+ gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
+ gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
+ gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
+ gate_dly[(count_gate*5)] <= cal4_gate_srl_a[0];
+ end
+ // check to see if we've found edge of window
+ if (!idel_set_wait)
+ cal4_state <= CAL4_FIND_EDGE;
+ end
+
+ // give additional time for RDEN_R pipe to clear from effects of
+ // previous pipeline (and IDELAY reset)
+ CAL4_RDEN_PIPE_CLR_WAIT: begin
+ // MIG 2.2: Bug fix - make sure to update GATE_DLY count, since
+ // possible for FIND_EDGE->RDEN_PIPE_CLR_WAIT->FIND_WINDOW
+ // transition (i.e. need to make sure the gate count updated in
+ // FIND_EDGE gets reflected in GATE_DLY by the time we reach
+ // state FIND_WINDOW) - previously GATE_DLY only being updated
+ // during state CAL4_IDEL_WAIT
+ if (SIM_ONLY != 0) begin
+ for (i = 0; i < DQS_WIDTH; i = i + 1) begin: loop_sim_gate_dly_pipe
+ gate_dly[(i*5)+4] <= cal4_gate_srl_a[4];
+ gate_dly[(i*5)+3] <= cal4_gate_srl_a[3];
+ gate_dly[(i*5)+2] <= cal4_gate_srl_a[2];
+ gate_dly[(i*5)+1] <= cal4_gate_srl_a[1];
+ gate_dly[(i*5)] <= cal4_gate_srl_a[0];
+ end
+ end else begin
+ gate_dly[(count_gate*5)+4] <= cal4_gate_srl_a[4];
+ gate_dly[(count_gate*5)+3] <= cal4_gate_srl_a[3];
+ gate_dly[(count_gate*5)+2] <= cal4_gate_srl_a[2];
+ gate_dly[(count_gate*5)+1] <= cal4_gate_srl_a[1];
+ gate_dly[(count_gate*5)] <= cal4_gate_srl_a[0];
+ end
+ // look for new window
+ if (calib_rden_pipe_cnt == 5'b00000)
+ cal4_state <= CAL4_FIND_WINDOW;
+ end
+
+ // increment/decrement DQS/DQ IDELAY for final adjustment
+ CAL4_ADJ_IDEL:
+ // add underflow protection for corner case when left edge found
+ // using fewer than MIN(BIT_TIME_TAPS,32) taps
+ if ((cal4_idel_adj_cnt == 6'b000000) ||
+ (cal4_dlyce_gate && !cal4_dlyinc_gate &&
+ (cal4_idel_tap_cnt == 6'b000001))) begin
+ cal4_state <= CAL4_DONE;
+ // stop when all gates calibrated, or gate[0] cal'ed (for sim)
+ if ((count_gate == DQS_WIDTH-1) || (SIM_ONLY != 0))
+ calib_done_tmp[3] <= 1'b1;
+ else
+ // need for VHDL simulation to prevent out-of-index error
+ next_count_gate <= count_gate + 1;
+ end else begin
+ cal4_idel_adj_cnt <= cal4_idel_adj_cnt - 1;
+ cal4_dlyce_gate <= 1'b1;
+ // whether inc or dec depends on whether left or right edge found
+ cal4_dlyinc_gate <= cal4_idel_adj_inc;
+ end
+
+ // wait for IDELAY output to settle after decrement. Check current
+ // COUNT_GATE value and decide if we're done
+ CAL4_DONE:
+ if (!idel_set_wait) begin
+ count_gate <= next_count_gate;
+ if (calib_done_tmp[3]) begin
+ calib_done[3] <= 1'b1;
+ cal4_state <= CAL4_IDLE;
+ end else begin
+ // request auto-refresh after every DQS group calibrated to
+ // avoid tRAS violation
+ cal4_ref_req <= 1'b1;
+ if (calib_ref_done)
+ cal4_state <= CAL4_INIT;
+ end
+ end
+ endcase
+ end
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_top.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_top.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_top.v (revision 3)
@@ -0,0 +1,181 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_usr_top.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Mon Aug 28 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module interfaces with the user. The user should provide the data
+// and various commands.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_usr_top #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter CS_BITS = 0,
+ parameter COL_WIDTH = 10,
+ parameter DQ_WIDTH = 72,
+ parameter DQ_PER_DQS = 8,
+ parameter APPDATA_WIDTH = 144,
+ parameter ECC_ENABLE = 0,
+ parameter DQS_WIDTH = 9,
+ parameter ROW_WIDTH = 14
+ )
+ (
+ input clk0,
+ input clk90,
+ input rst0,
+ input [DQ_WIDTH-1:0] rd_data_in_rise,
+ input [DQ_WIDTH-1:0] rd_data_in_fall,
+ input [DQS_WIDTH-1:0] phy_calib_rden,
+ input [DQS_WIDTH-1:0] phy_calib_rden_sel,
+ output rd_data_valid,
+ output [APPDATA_WIDTH-1:0] rd_data_fifo_out,
+ input [2:0] app_af_cmd,
+ input [30:0] app_af_addr,
+ input app_af_wren,
+ input ctrl_af_rden,
+ output [2:0] af_cmd,
+ output [30:0] af_addr,
+ output af_empty,
+ output app_af_afull,
+ output [1:0] rd_ecc_error,
+ input app_wdf_wren,
+ input [APPDATA_WIDTH-1:0] app_wdf_data,
+ input [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
+ input wdf_rden,
+ output app_wdf_afull,
+ output [(2*DQ_WIDTH)-1:0] wdf_data,
+ output [((2*DQ_WIDTH)/8)-1:0] wdf_mask_data
+ );
+
+ wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_fall;
+ wire [(APPDATA_WIDTH/2)-1:0] i_rd_data_fifo_out_rise;
+
+ //***************************************************************************
+
+ assign rd_data_fifo_out = {i_rd_data_fifo_out_fall,
+ i_rd_data_fifo_out_rise};
+
+ // read data de-skew and ECC calculation
+ ddr2_usr_rd #
+ (
+ .DQ_PER_DQS (DQ_PER_DQS),
+ .ECC_ENABLE (ECC_ENABLE),
+ .APPDATA_WIDTH (APPDATA_WIDTH),
+ .DQS_WIDTH (DQS_WIDTH)
+ )
+ u_usr_rd
+ (
+ .clk0 (clk0),
+ .rst0 (rst0),
+ .rd_data_in_rise (rd_data_in_rise),
+ .rd_data_in_fall (rd_data_in_fall),
+ .rd_ecc_error (rd_ecc_error),
+ .ctrl_rden (phy_calib_rden),
+ .ctrl_rden_sel (phy_calib_rden_sel),
+ .rd_data_valid (rd_data_valid),
+ .rd_data_out_rise (i_rd_data_fifo_out_rise),
+ .rd_data_out_fall (i_rd_data_fifo_out_fall)
+ );
+
+ // Command/Addres FIFO
+ ddr2_usr_addr_fifo #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .CS_BITS (CS_BITS),
+ .ROW_WIDTH (ROW_WIDTH)
+ )
+ u_usr_addr_fifo
+ (
+ .clk0 (clk0),
+ .rst0 (rst0),
+ .app_af_cmd (app_af_cmd),
+ .app_af_addr (app_af_addr),
+ .app_af_wren (app_af_wren),
+ .ctrl_af_rden (ctrl_af_rden),
+ .af_cmd (af_cmd),
+ .af_addr (af_addr),
+ .af_empty (af_empty),
+ .app_af_afull (app_af_afull)
+ );
+
+ ddr2_usr_wr #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .CS_BITS (CS_BITS),
+ .DQ_WIDTH (DQ_WIDTH),
+ .APPDATA_WIDTH (APPDATA_WIDTH),
+ .ECC_ENABLE (ECC_ENABLE),
+ .ROW_WIDTH (ROW_WIDTH)
+ )
+ u_usr_wr
+ (
+ .clk0 (clk0),
+ .clk90 (clk90),
+ .rst0 (rst0),
+ .app_wdf_wren (app_wdf_wren),
+ .app_wdf_data (app_wdf_data),
+ .app_wdf_mask_data (app_wdf_mask_data),
+ .wdf_rden (wdf_rden),
+ .app_wdf_afull (app_wdf_afull),
+ .wdf_data (wdf_data),
+ .wdf_mask_data (wdf_mask_data)
+ );
+
+endmodule
\ No newline at end of file
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_idelay_ctrl.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_idelay_ctrl.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_idelay_ctrl.v (revision 3)
@@ -0,0 +1,87 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_idelay_ctrl.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Wed Aug 16 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module instantiates the IDELAYCTRL primitive of the Virtex-5 device
+// which continuously calibrates the IDELAY elements in the region in case of
+// varying operating conditions. It takes a 200MHz clock as an input
+//Reference:
+//Revision History:
+// Rev 1.1 - Parameter IODELAY_GRP added and constraint IODELAY_GROUP added
+// on IOELAYCTRL primitive. Generate logic on IDELAYCTRL removed
+// since tools will replicate idelactrl primitives.PK. 11/27/08
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_idelay_ctrl #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter IODELAY_GRP = "IODELAY_MIG"
+ )
+
+ (
+ input clk200,
+ input rst200,
+ output idelay_ctrl_rdy
+ );
+
+ (* IODELAY_GROUP = IODELAY_GRP *) IDELAYCTRL u_idelayctrl
+ (
+ .RDY(idelay_ctrl_rdy),
+ .REFCLK(clk200),
+ .RST(rst200)
+ );
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_rd.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_rd.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl/ddr2_usr_rd.v (revision 3)
@@ -0,0 +1,297 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_usr_rd.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Tue Aug 29 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// The delay between the read data with respect to the command issued is
+// calculted in terms of no. of clocks. This data is then stored into the
+// FIFOs and then read back and given as the ouput for comparison.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_usr_rd #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter DQ_PER_DQS = 8,
+ parameter DQS_WIDTH = 9,
+ parameter APPDATA_WIDTH = 144,
+ parameter ECC_WIDTH = 72,
+ parameter ECC_ENABLE = 0
+ )
+ (
+ input clk0,
+ input rst0,
+ input [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_rise,
+ input [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_fall,
+ input [DQS_WIDTH-1:0] ctrl_rden,
+ input [DQS_WIDTH-1:0] ctrl_rden_sel,
+ output reg [1:0] rd_ecc_error,
+ output rd_data_valid,
+ output reg [(APPDATA_WIDTH/2)-1:0] rd_data_out_rise,
+ output reg [(APPDATA_WIDTH/2)-1:0] rd_data_out_fall
+ );
+
+ // determine number of FIFO72's to use based on data width
+ localparam RDF_FIFO_NUM = ((APPDATA_WIDTH/2)+63)/64;
+
+ reg [DQS_WIDTH-1:0] ctrl_rden_r;
+ wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data;
+ reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_fall_r;
+ reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rd_data_in_rise_r;
+ wire rden;
+ reg [DQS_WIDTH-1:0] rden_sel_r
+ /* synthesis syn_preserve=1 */;
+ wire [DQS_WIDTH-1:0] rden_sel_mux;
+ wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data;
+
+ // ECC specific signals
+ wire [((RDF_FIFO_NUM -1) *2)+1:0] db_ecc_error;
+ reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data_r;
+ reg fifo_rden_r0;
+ reg fifo_rden_r1;
+ reg fifo_rden_r2;
+ reg fifo_rden_r3;
+ reg fifo_rden_r4;
+ reg fifo_rden_r5;
+ reg fifo_rden_r6;
+ wire [(APPDATA_WIDTH/2)-1:0] rd_data_out_fall_temp;
+ wire [(APPDATA_WIDTH/2)-1:0] rd_data_out_rise_temp;
+ reg rst_r;
+ reg [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data_r;
+ wire [((RDF_FIFO_NUM -1) *2)+1:0] sb_ecc_error;
+
+
+ //***************************************************************************
+
+ always @(posedge clk0) begin
+ rden_sel_r <= ctrl_rden_sel;
+ ctrl_rden_r <= ctrl_rden;
+ rd_data_in_rise_r <= rd_data_in_rise;
+ rd_data_in_fall_r <= rd_data_in_fall;
+ end
+
+ // Instantiate primitive to allow this flop to be attached to multicycle
+ // path constraint in UCF. Multicycle path allowed for data from read FIFO.
+ // This is the same signal as RDEN_SEL_R, but is only used to select data
+ // (does not affect control signals)
+ genvar rd_i;
+ generate
+ for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rden_sel_mux
+ FDRSE u_ff_rden_sel_mux
+ (
+ .Q (rden_sel_mux[rd_i]),
+ .C (clk0),
+ .CE (1'b1),
+ .D (ctrl_rden_sel[rd_i]),
+ .R (1'b0),
+ .S (1'b0)
+ ) /* synthesis syn_preserve=1 */;
+ end
+ endgenerate
+
+ // determine correct read data valid signal timing
+ assign rden = (rden_sel_r[0]) ? ctrl_rden[0] : ctrl_rden_r[0];
+
+ // assign data based on the skew
+ genvar data_i;
+ generate
+ for(data_i = 0; data_i < DQS_WIDTH; data_i = data_i+1) begin: gen_data
+ assign rise_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+ (data_i*DQ_PER_DQS)]
+ = (rden_sel_mux[data_i]) ?
+ rd_data_in_rise[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1) :
+ (data_i*DQ_PER_DQS)] :
+ rd_data_in_rise_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+ (data_i*DQ_PER_DQS)];
+ assign fall_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+ (data_i*DQ_PER_DQS)]
+ = (rden_sel_mux[data_i]) ?
+ rd_data_in_fall[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+ (data_i*DQ_PER_DQS)] :
+ rd_data_in_fall_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
+ (data_i*DQ_PER_DQS)];
+ end
+ endgenerate
+
+ // Generate RST for FIFO reset AND for read/write enable:
+ // ECC FIFO always being read from and written to
+ always @(posedge clk0)
+ rst_r <= rst0;
+
+ genvar rdf_i;
+ generate
+ if (ECC_ENABLE) begin
+ always @(posedge clk0) begin
+ rd_ecc_error[0] <= (|sb_ecc_error) & fifo_rden_r5;
+ rd_ecc_error[1] <= (|db_ecc_error) & fifo_rden_r5;
+ rd_data_out_rise <= rd_data_out_rise_temp;
+ rd_data_out_fall <= rd_data_out_fall_temp;
+ rise_data_r <= rise_data;
+ fall_data_r <= fall_data;
+ end
+
+ // can use any of the read valids, they're all delayed by same amount
+ assign rd_data_valid = fifo_rden_r6;
+
+ // delay read valid to take into account max delay difference btw
+ // the read enable coming from the different DQS groups
+ always @(posedge clk0) begin
+ if (rst0) begin
+ fifo_rden_r0 <= 1'b0;
+ fifo_rden_r1 <= 1'b0;
+ fifo_rden_r2 <= 1'b0;
+ fifo_rden_r3 <= 1'b0;
+ fifo_rden_r4 <= 1'b0;
+ fifo_rden_r5 <= 1'b0;
+ fifo_rden_r6 <= 1'b0;
+ end else begin
+ fifo_rden_r0 <= rden;
+ fifo_rden_r1 <= fifo_rden_r0;
+ fifo_rden_r2 <= fifo_rden_r1;
+ fifo_rden_r3 <= fifo_rden_r2;
+ fifo_rden_r4 <= fifo_rden_r3;
+ fifo_rden_r5 <= fifo_rden_r4;
+ fifo_rden_r6 <= fifo_rden_r5;
+ end
+ end
+
+ for (rdf_i = 0; rdf_i < RDF_FIFO_NUM; rdf_i = rdf_i + 1) begin: gen_rdf
+
+ FIFO36_72 # // rise fifo
+ (
+ .ALMOST_EMPTY_OFFSET (9'h007),
+ .ALMOST_FULL_OFFSET (9'h00F),
+ .DO_REG (1), // extra CC output delay
+ .EN_ECC_WRITE ("FALSE"),
+ .EN_ECC_READ ("TRUE"),
+ .EN_SYN ("FALSE"),
+ .FIRST_WORD_FALL_THROUGH ("FALSE")
+ )
+ u_rdf
+ (
+ .ALMOSTEMPTY (),
+ .ALMOSTFULL (),
+ .DBITERR (db_ecc_error[rdf_i + rdf_i]),
+ .DO (rd_data_out_rise_temp[(64*(rdf_i+1))-1:
+ (64 *rdf_i)]),
+ .DOP (),
+ .ECCPARITY (),
+ .EMPTY (),
+ .FULL (),
+ .RDCOUNT (),
+ .RDERR (),
+ .SBITERR (sb_ecc_error[rdf_i + rdf_i]),
+ .WRCOUNT (),
+ .WRERR (),
+ .DI (rise_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
+ (64 *rdf_i)+(rdf_i*8)]),
+ .DIP (rise_data_r[(72*(rdf_i+1))-1:
+ (64*(rdf_i+1))+ (8*rdf_i)]),
+ .RDCLK (clk0),
+ .RDEN (~rst_r),
+ .RST (rst_r),
+ .WRCLK (clk0),
+ .WREN (~rst_r)
+ );
+
+ FIFO36_72 # // fall_fifo
+ (
+ .ALMOST_EMPTY_OFFSET (9'h007),
+ .ALMOST_FULL_OFFSET (9'h00F),
+ .DO_REG (1), // extra CC output delay
+ .EN_ECC_WRITE ("FALSE"),
+ .EN_ECC_READ ("TRUE"),
+ .EN_SYN ("FALSE"),
+ .FIRST_WORD_FALL_THROUGH ("FALSE")
+ )
+ u_rdf1
+ (
+ .ALMOSTEMPTY (),
+ .ALMOSTFULL (),
+ .DBITERR (db_ecc_error[(rdf_i+1) + rdf_i]),
+ .DO (rd_data_out_fall_temp[(64*(rdf_i+1))-1:
+ (64 *rdf_i)]),
+ .DOP (),
+ .ECCPARITY (),
+ .EMPTY (),
+ .FULL (),
+ .RDCOUNT (),
+ .RDERR (),
+ .SBITERR (sb_ecc_error[(rdf_i+1) + rdf_i]),
+ .WRCOUNT (),
+ .WRERR (),
+ .DI (fall_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
+ (64*rdf_i)+(rdf_i*8)]),
+ .DIP (fall_data_r[(72*(rdf_i+1))-1:
+ (64*(rdf_i+1))+ (8*rdf_i)]),
+ .RDCLK (clk0),
+ .RDEN (~rst_r),
+ .RST (rst_r), // or can use rst0
+ .WRCLK (clk0),
+ .WREN (~rst_r)
+ );
+ end
+ end else begin
+ assign rd_data_valid = fifo_rden_r0;
+ always @(posedge clk0) begin
+ rd_data_out_rise <= rise_data;
+ rd_data_out_fall <= fall_data;
+ fifo_rden_r0 <= rden;
+ end
+ end
+ endgenerate
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/rtl
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/rtl (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/rtl (revision 3)
rtl/ipcore_dir/MEMCtrl/user_design/rtl
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_cmp.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_cmp.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_cmp.v (revision 3)
@@ -0,0 +1,266 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_tb_test_cmp.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Fri Sep 01 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module generates the error signal in case of bit errors. It compares
+// the read data with expected data value.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_tb_test_cmp #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter DQ_WIDTH = 72,
+ parameter APPDATA_WIDTH = 144,
+ parameter ECC_ENABLE = 0
+ )
+ (
+ input clk,
+ input rst,
+ input phy_init_done,
+ input rd_data_valid,
+ input [APPDATA_WIDTH-1:0] app_cmp_data,
+ input [APPDATA_WIDTH-1:0] rd_data_fifo_in,
+ output reg error,
+ output reg error_cmp
+ );
+
+ wire [(APPDATA_WIDTH/16)-1:0] byte_err_fall;
+ reg [(APPDATA_WIDTH/16)-1:0] byte_err_fall_r;
+ wire [(APPDATA_WIDTH/16)-1:0] byte_err_rise;
+ reg [(APPDATA_WIDTH/16)-1:0] byte_err_rise_r;
+ wire [(APPDATA_WIDTH/2)-1:0] cmp_data_fall;
+ wire [(APPDATA_WIDTH/2)-1:0] cmp_data_rise;
+ wire [APPDATA_WIDTH-1:0] cmp_data_r;
+ reg [APPDATA_WIDTH-1:0] cmp_data_r1;
+ reg cmp_start;
+ wire [(APPDATA_WIDTH/2)-1:0] data_fall_r;
+ wire [(APPDATA_WIDTH/2)-1:0] data_rise_r;
+ reg err_fall;
+ reg err_rise;
+ reg error_tmp_r;
+ wire error_tmp_r1;
+ wire error_tmp_r2;
+ wire [APPDATA_WIDTH-1:0] rd_data_r;
+ wire [APPDATA_WIDTH-1:0] rd_data_r1;
+ reg [APPDATA_WIDTH-1:0] rd_data_r2;
+ wire rd_data_valid_r;
+ reg rd_data_valid_r1;
+ reg rd_data_valid_r2;
+ reg rst_r
+ /* synthesis syn_preserve = 1 */;
+ reg rst_r1
+ /* synthesis syn_maxfan = 10 */;
+
+ // XST attributes for local reset "tree"
+ // synthesis attribute shreg_extract of rst_r is "no";
+ // synthesis attribute shreg_extract of rst_r1 is "no";
+ // synthesis attribute equivalent_register_removal of rst_r is "no"
+
+ //***************************************************************************
+
+ // local reset "tree" for controller logic only. Create this to ease timing
+ // on reset path. Prohibit equivalent register removal on RST_R to prevent
+ // "sharing" with other local reset trees (caution: make sure global fanout
+ // limit is set to larger than fanout on RST_R, otherwise SLICES will be
+ // used for fanout control on RST_R.
+ always @(posedge clk) begin
+ rst_r <= rst;
+ rst_r1 <= rst_r;
+ end
+
+ // instantiate discrete flops for better timing
+ genvar rd_data_i;
+ generate
+ for (rd_data_i = 0; rd_data_i < APPDATA_WIDTH;
+ rd_data_i = rd_data_i + 1) begin: gen_rd_data
+ FDRSE ff_rd_data
+ (
+ .Q (rd_data_r[rd_data_i]),
+ .C (clk),
+ .CE (1'b1),
+ .D (rd_data_fifo_in[rd_data_i]),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ FDRSE ff_rd_data_r1
+ (
+ .Q (rd_data_r1[rd_data_i]),
+ .C (clk),
+ .CE (1'b1),
+ .D (rd_data_r[rd_data_i]),
+ .R (1'b0),
+ .S (1'b0)
+ );
+ end
+ endgenerate
+
+ genvar cmp_data_i;
+ generate
+ for (cmp_data_i = 0; cmp_data_i < APPDATA_WIDTH;
+ cmp_data_i = cmp_data_i + 1) begin: gen_cmp_data
+ FDRSE ff_cmp_data
+ (
+ .Q (cmp_data_r[cmp_data_i]),
+ .C (clk),
+ .CE (1'b1),
+ .D (app_cmp_data[cmp_data_i]),
+ .R (1'b0),
+ .S (1'b0)
+ );
+ end
+ endgenerate
+
+ assign data_fall_r = rd_data_r2[APPDATA_WIDTH-1:(APPDATA_WIDTH/2)];
+ assign data_rise_r = rd_data_r2[(APPDATA_WIDTH/2)-1:0];
+ assign cmp_data_fall = cmp_data_r[APPDATA_WIDTH-1:(APPDATA_WIDTH/2)];
+ assign cmp_data_rise = cmp_data_r[(APPDATA_WIDTH/2)-1:0];
+
+ // Instantiate ff for timing.
+ FDRSE ff_rd_data_valid_r
+ (
+ .Q (rd_data_valid_r),
+ .C (clk),
+ .CE (1'b1),
+ .D (rd_data_valid),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ always @(posedge clk) begin
+ if (rst_r1) begin
+ rd_data_valid_r1 <= 1'd0;
+ end else begin
+ rd_data_valid_r1 <= rd_data_valid_r & phy_init_done;
+ end
+ end
+
+ always @(posedge clk)begin
+ rd_data_r2 <= rd_data_r1;
+ cmp_data_r1 <= cmp_data_r;
+ rd_data_valid_r2 <= rd_data_valid_r1;
+ end
+
+ genvar cmp_i;
+ generate
+ for (cmp_i = 0; cmp_i < APPDATA_WIDTH/16; cmp_i = cmp_i + 1) begin: gen_cmp
+ assign byte_err_fall[cmp_i]
+ = (rd_data_valid_r2 &&
+ (data_fall_r[8*(cmp_i+1)-1:8*cmp_i] !=
+ cmp_data_fall[8*(cmp_i+1)-1:8*cmp_i]));
+ assign byte_err_rise[cmp_i]
+ = (rd_data_valid_r2 &&
+ (data_rise_r[8*(cmp_i+1)-1:8*cmp_i] !=
+ cmp_data_rise[8*(cmp_i+1)-1:8*cmp_i]));
+ end
+ endgenerate
+
+ always @(posedge clk) begin
+ byte_err_rise_r <= byte_err_rise;
+ byte_err_fall_r <= byte_err_fall;
+ end
+
+ always @(posedge clk)
+ if (rst_r1) begin
+ err_rise <= 1'bx;
+ err_fall <= 1'bx;
+ cmp_start <= 1'b0;
+ error_tmp_r <= 1'b0;
+ end else begin
+ err_rise <= | byte_err_rise_r;
+ err_fall <= | byte_err_fall_r;
+ // start comparing when initialization/calibration complete, and we
+ // get first valid readback
+ if (rd_data_valid_r2)
+ cmp_start <= 1'b1;
+ if (cmp_start && !error_tmp_r)
+ error_tmp_r <= err_rise | err_fall;
+ //synthesis translate_off
+ if ((err_rise || err_fall) && cmp_start)
+ $display ("ERROR at time %t" , $time);
+ //synthesis translate_on
+ end
+
+ // FF inst to force synthesis to infer ff's.
+ // Done for timing.
+ FDRSE ff_error_1
+ (
+ .Q (error_tmp_r1),
+ .C (clk),
+ .CE (1'b1),
+ .D (error_tmp_r),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ FDRSE ff_error_2
+ (
+ .Q (error_tmp_r2),
+ .C (clk),
+ .CE (1'b1),
+ .D (error_tmp_r1),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ always @(posedge clk) begin
+ error <= error_tmp_r2;
+ error_cmp <= err_rise | err_fall;
+ end
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_data_gen.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_data_gen.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_data_gen.v (revision 3)
@@ -0,0 +1,274 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_tb_test_data_gen.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Fri Sep 01 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module contains the data generation logic for the synthesizable
+// testbench.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_tb_test_data_gen #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter DM_WIDTH = 9,
+ parameter DQ_WIDTH = 72,
+ parameter APPDATA_WIDTH = 144,
+ parameter ECC_ENABLE = 0
+ )
+ (
+ input clk,
+ input rst,
+ input wr_data_en,
+ input rd_data_valid,
+ output app_wdf_wren,
+ output reg [APPDATA_WIDTH-1:0] app_wdf_data,
+ output reg [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
+ output [APPDATA_WIDTH-1:0] app_cmp_data
+ );
+
+ localparam WR_IDLE_FIRST_DATA = 2'b00;
+ localparam WR_SECOND_DATA = 2'b01;
+ localparam WR_THIRD_DATA = 2'b10;
+ localparam WR_FOURTH_DATA = 2'b11;
+ localparam RD_IDLE_FIRST_DATA = 2'b00;
+ localparam RD_SECOND_DATA = 2'b01;
+ localparam RD_THIRD_DATA = 2'b10;
+ localparam RD_FOURTH_DATA = 2'b11;
+
+ reg [APPDATA_WIDTH-1:0] app_wdf_data_r;
+ reg [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data_r;
+ wire app_wdf_wren_r;
+ reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_fall;
+ reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_rise;
+ wire rd_data_valid_r;
+ reg [1:0] rd_state;
+ reg rst_r
+ /* synthesis syn_preserve = 1 */;
+ reg rst_r1
+ /* synthesis syn_maxfan = 10 */;
+ wire [APPDATA_WIDTH-1:0] wr_data;
+ reg wr_data_en_r;
+ reg [(APPDATA_WIDTH/2)-1:0] wr_data_fall
+ /* synthesis syn_maxfan = 2 */;
+ reg [(APPDATA_WIDTH/2)-1:0] wr_data_rise
+ /* synthesis syn_maxfan = 2 */;
+ wire [(APPDATA_WIDTH/8)-1:0] wr_mask_data;
+ wire [(APPDATA_WIDTH/16)-1:0] wr_mask_data_fall;
+ wire [(APPDATA_WIDTH/16)-1:0] wr_mask_data_rise;
+ reg [1:0] wr_state;
+
+ // XST attributes for local reset "tree"
+ // synthesis attribute shreg_extract of rst_r is "no";
+ // synthesis attribute shreg_extract of rst_r1 is "no";
+ // synthesis attribute equivalent_register_removal of rst_r is "no"
+
+ //***************************************************************************
+
+ // local reset "tree" for controller logic only. Create this to ease timing
+ // on reset path. Prohibit equivalent register removal on RST_R to prevent
+ // "sharing" with other local reset trees (caution: make sure global fanout
+ // limit is set to larger than fanout on RST_R, otherwise SLICES will be
+ // used for fanout control on RST_R.
+ always @(posedge clk) begin
+ rst_r <= rst;
+ rst_r1 <= rst_r;
+ end
+
+ always @(posedge clk) begin
+ app_wdf_data_r <= wr_data;
+ app_wdf_mask_data_r <= wr_mask_data;
+ app_wdf_data <= app_wdf_data_r;
+ app_wdf_mask_data <= app_wdf_mask_data_r;
+ end
+
+ // inst ff for timing
+ FDRSE ff_wdf_wren
+ (
+ .Q (app_wdf_wren_r),
+ .C (clk),
+ .CE (1'b1),
+ .D (wr_data_en_r),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ FDRSE ff_wdf_wren_r
+ (
+ .Q (app_wdf_wren),
+ .C (clk),
+ .CE (1'b1),
+ .D (app_wdf_wren_r),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ FDRSE ff_rd_data_valid_r
+ (
+ .Q (rd_data_valid_r),
+ .C (clk),
+ .CE (1'b1),
+ .D (rd_data_valid),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ //***************************************************************************
+ // DATA generation for WRITE DATA FIFOs & for READ DATA COMPARE
+ //***************************************************************************
+
+ assign wr_data = {wr_data_fall, wr_data_rise};
+ assign wr_mask_data = {wr_mask_data_fall, wr_mask_data_rise};
+
+ //*****************************************************************
+ // For now, don't vary data masks
+ //*****************************************************************
+
+ assign wr_mask_data_rise = {(APPDATA_WIDTH/8){1'b0}};
+ assign wr_mask_data_fall = {(APPDATA_WIDTH/8){1'b0}};
+
+ //*****************************************************************
+ // Write data logic
+ //*****************************************************************
+
+ // write data generation
+ //synthesis attribute max_fanout of wr_data_fall is 2
+ //synthesis attribute max_fanout of wr_data_rise is 2
+ always @(posedge clk) begin
+ if (rst_r1) begin
+ wr_data_rise <= {(APPDATA_WIDTH/2){1'bx}};
+ wr_data_fall <= {(APPDATA_WIDTH/2){1'bx}};
+ wr_state <= WR_IDLE_FIRST_DATA;
+ end else begin
+ case (wr_state)
+ WR_IDLE_FIRST_DATA:
+ if (wr_data_en) begin
+ wr_data_rise <= {(APPDATA_WIDTH/2){1'b1}}; // 0xF
+ wr_data_fall <= {(APPDATA_WIDTH/2){1'b0}}; // 0x0
+ wr_state <= WR_SECOND_DATA;
+ end
+ WR_SECOND_DATA:
+ if (wr_data_en) begin
+ wr_data_rise <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
+ wr_data_fall <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
+ wr_state <= WR_THIRD_DATA;
+ end
+ WR_THIRD_DATA:
+ if (wr_data_en) begin
+ wr_data_rise <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
+ wr_data_fall <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
+ wr_state <= WR_FOURTH_DATA;
+ end
+ WR_FOURTH_DATA:
+ if (wr_data_en) begin
+ wr_data_rise <= {(APPDATA_WIDTH/8){4'b1001}}; // 0x9
+ wr_data_fall <= {(APPDATA_WIDTH/8){4'b0110}}; // 0x6
+ wr_state <= WR_IDLE_FIRST_DATA;
+ end
+ endcase
+ end
+ end
+
+ always @(posedge clk)
+ if (rst_r1)
+ wr_data_en_r <= 1'b0;
+ else
+ wr_data_en_r <= wr_data_en;
+
+ //*****************************************************************
+ // Read data logic
+ //*****************************************************************
+
+ // read comparison data generation
+ always @(posedge clk)
+ if (rst_r1) begin
+ rd_data_pat_rise <= {(APPDATA_WIDTH/2){1'bx}};
+ rd_data_pat_fall <= {(APPDATA_WIDTH/2){1'bx}};
+ rd_state <= RD_IDLE_FIRST_DATA;
+ end else begin
+ case (rd_state)
+ RD_IDLE_FIRST_DATA:
+ if (rd_data_valid_r)
+ begin
+ rd_data_pat_rise <= {(APPDATA_WIDTH/2){1'b1}}; // 0xF
+ rd_data_pat_fall <= {(APPDATA_WIDTH/2){1'b0}}; // 0x0
+ rd_state <= RD_SECOND_DATA;
+ end
+ RD_SECOND_DATA:
+ if (rd_data_valid_r) begin
+ rd_data_pat_rise <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
+ rd_data_pat_fall <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
+ rd_state <= RD_THIRD_DATA;
+ end
+ RD_THIRD_DATA:
+ if (rd_data_valid_r) begin
+ rd_data_pat_rise <= {(APPDATA_WIDTH/4){2'b01}}; // 0x5
+ rd_data_pat_fall <= {(APPDATA_WIDTH/4){2'b10}}; // 0xA
+ rd_state <= RD_FOURTH_DATA;
+ end
+ RD_FOURTH_DATA:
+ if (rd_data_valid_r) begin
+ rd_data_pat_rise <= {(APPDATA_WIDTH/8){4'b1001}}; // 0x9
+ rd_data_pat_fall <= {(APPDATA_WIDTH/8){4'b0110}}; // 0x6
+ rd_state <= RD_IDLE_FIRST_DATA;
+ end
+ endcase
+ end
+
+ //data to the compare circuit during read
+ assign app_cmp_data = {rd_data_pat_fall, rd_data_pat_rise};
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_addr_gen.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_addr_gen.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_addr_gen.v (revision 3)
@@ -0,0 +1,239 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007, 2008 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_tb_test_addr_gen.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Fri Sep 01 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// The address for the memory and the various user commands can be given
+// through this module. It instantiates the block RAM which stores all the
+// information in particular sequence. The data stored should be in a
+// sequence starting from LSB:
+// column address, row address, bank address, commands.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_tb_test_addr_gen #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter COL_WIDTH = 10,
+ parameter ROW_WIDTH = 14
+ )
+ (
+ input clk,
+ input rst,
+ input wr_addr_en,
+ output reg [2:0] app_af_cmd,
+ output reg [30:0] app_af_addr,
+ output reg app_af_wren
+ );
+
+ // RAM initialization patterns
+ // NOTE: Not all bits in each range may be used (e.g. in an application
+ // using only 10 column bits, bits[11:10] of ROM output will be unused
+ // COLUMN = [11:0]
+ // ROW = [27:12]
+ // BANK = [30:28]
+ // CHIP = [31]
+ // COMMAND = [35:32]
+
+ localparam RAM_INIT_00 = {128'h800020C0_800020C8_000020D0_000020D8,
+ 128'h000010E0_000010E8_800010F0_800010F8};
+ localparam RAM_INIT_01 = {128'h800020C0_800020C8_000020D0_000020D8,
+ 128'h000010E0_000010E8_800010F0_800010F8};
+ localparam RAM_INIT_02 = {128'h100040C0_100040C8_900040D0_900040D8,
+ 128'h900030E0_900030E8_100030F0_100030F8};
+ localparam RAM_INIT_03 = {128'h100040C0_100040C8_900040D0_900040D8,
+ 128'h900030E0_900030E8_100030F0_100030F8};
+ localparam RAM_INIT_04 = {128'hA00060C0_200060C8_200060D0_A00060D8,
+ 128'h200050E0_A00050E8_A00050F0_200050F8};
+ localparam RAM_INIT_05 = {128'hA00060C0_200060C8_200060D0_A00060D8,
+ 128'h200050E0_A00050E8_A00050F0_200050F8};
+ localparam RAM_INIT_06 = {128'h300080C0_B00080C8_B00080D0_300080D8,
+ 128'hB00070E0_300070E8_300070F0_B00070F8};
+ localparam RAM_INIT_07 = {128'h300080C0_B00080C8_B00080D0_300080D8,
+ 128'hB00070E0_300070E8_300070F0_B00070F8};
+ localparam RAM_INITP_00 = {128'h11111111_00000000_11111111_00000000,
+ 128'h11111111_00000000_11111111_00000000};
+
+ reg wr_addr_en_r1;
+ reg [2:0] af_cmd_r;
+ reg [30:0] af_addr_r;
+ reg af_wren_r;
+ wire [15:0] ramb_addr;
+ wire [35:0] ramb_dout;
+ reg rst_r
+ /* synthesis syn_preserve = 1 */;
+ reg rst_r1
+ /* synthesis syn_maxfan = 10 */;
+ reg [5:0] wr_addr_cnt;
+ reg wr_addr_en_r0;
+
+ // XST attributes for local reset "tree"
+ // synthesis attribute shreg_extract of rst_r is "no";
+ // synthesis attribute shreg_extract of rst_r1 is "no";
+ // synthesis attribute equivalent_register_removal of rst_r is "no"
+
+ //*****************************************************************
+
+ // local reset "tree" for controller logic only. Create this to ease timing
+ // on reset path. Prohibit equivalent register removal on RST_R to prevent
+ // "sharing" with other local reset trees (caution: make sure global fanout
+ // limit is set to larger than fanout on RST_R, otherwise SLICES will be
+ // used for fanout control on RST_R.
+ always @(posedge clk) begin
+ rst_r <= rst;
+ rst_r1 <= rst_r;
+ end
+
+ //***************************************************************************
+ // ADDRESS generation for Write and Read Address FIFOs:
+ // ROM with address patterns
+ // 512x36 mode is used with addresses 0-127 for storing write addresses and
+ // addresses (128-511) for storing read addresses
+ // INIP_OO: read 1
+ // INIP_OO: write 0
+ //***************************************************************************
+
+ assign ramb_addr = {5'b00000, wr_addr_cnt, 5'b00000};
+
+ RAMB36 #
+ (
+ .READ_WIDTH_A (36),
+ .READ_WIDTH_B (36),
+ .DOA_REG (1), // register to help timing
+ .INIT_00 (RAM_INIT_00),
+ .INIT_01 (RAM_INIT_01),
+ .INIT_02 (RAM_INIT_02),
+ .INIT_03 (RAM_INIT_03),
+ .INIT_04 (RAM_INIT_04),
+ .INIT_05 (RAM_INIT_05),
+ .INIT_06 (RAM_INIT_06),
+ .INIT_07 (RAM_INIT_07),
+ .INITP_00 (RAM_INITP_00)
+ )
+ u_wr_rd_addr_lookup
+ (
+ .CASCADEOUTLATA (),
+ .CASCADEOUTLATB (),
+ .CASCADEOUTREGA (),
+ .CASCADEOUTREGB (),
+ .DOA (ramb_dout[31:0]),
+ .DOB (),
+ .DOPA (ramb_dout[35:32]),
+ .DOPB (),
+ .ADDRA (ramb_addr),
+ .ADDRB (16'h0000),
+ .CASCADEINLATA (),
+ .CASCADEINLATB (),
+ .CASCADEINREGA (),
+ .CASCADEINREGB (),
+ .CLKA (clk),
+ .CLKB (clk),
+ .DIA (32'b0),
+ .DIB (32'b0),
+ .DIPA (4'b0),
+ .DIPB (4'b0),
+ .ENA (1'b1),
+ .ENB (1'b1),
+ .REGCEA (1'b1),
+ .REGCEB (1'b1),
+ .SSRA (1'b0),
+ .SSRB (1'b0),
+ .WEA (4'b0000),
+ .WEB (4'b0000)
+ );
+
+ // register backend enables / FIFO enables
+ // write enable for Command/Address FIFO is generated 2 CC after WR_ADDR_EN
+ // (takes 2 CC to come out of test RAM)
+ always @(posedge clk)
+ if (rst_r1) begin
+ app_af_wren <= 1'b0;
+ wr_addr_en_r0 <= 1'b0;
+ wr_addr_en_r1 <= 1'b0;
+ af_wren_r <= 1'b0;
+ end else begin
+ wr_addr_en_r0 <= wr_addr_en;
+ wr_addr_en_r1 <= wr_addr_en_r0;
+ af_wren_r <= wr_addr_en_r1;
+ app_af_wren <= af_wren_r;
+ end
+
+ // FIFO addresses
+ always @(posedge clk) begin
+ af_addr_r <= {30{1'b0}};
+ af_addr_r[COL_WIDTH-1:0] <= ramb_dout[COL_WIDTH-1:0];
+ af_addr_r[ROW_WIDTH+COL_WIDTH-1:COL_WIDTH]
+ <= ramb_dout[ROW_WIDTH+11:12];
+ af_addr_r[BANK_WIDTH+ROW_WIDTH+COL_WIDTH-1:ROW_WIDTH+COL_WIDTH]
+ <= ramb_dout[BANK_WIDTH+27:28];
+ af_addr_r[BANK_WIDTH+ROW_WIDTH+COL_WIDTH]
+ <= ramb_dout[31];
+ // only reads and writes are supported for now
+ af_cmd_r <= {1'b0, ramb_dout[33:32]};
+ app_af_cmd <= af_cmd_r;
+ app_af_addr <= af_addr_r;
+ end
+
+ // address input for RAM
+ always @ (posedge clk)
+ if (rst_r1)
+ wr_addr_cnt <= 6'b000000;
+ else if (wr_addr_en)
+ wr_addr_cnt <= wr_addr_cnt + 1;
+
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_top.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_top.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_top.v (revision 3)
@@ -0,0 +1,322 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_tb_top.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Fri Sep 01 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module is the synthesizable test bench for the memory interface.
+// This Test bench is to compare the write and the read data and generate
+// an error flag.
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_tb_top #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter COL_WIDTH = 10,
+ parameter DM_WIDTH = 9,
+ parameter DQ_WIDTH = 72,
+ parameter ROW_WIDTH = 14,
+ parameter APPDATA_WIDTH = 144,
+ parameter ECC_ENABLE = 0,
+ parameter BURST_LEN = 4
+ )
+ (
+ input clk0,
+ input rst0,
+ input app_af_afull,
+ input app_wdf_afull,
+ input rd_data_valid,
+ input [APPDATA_WIDTH-1:0] rd_data_fifo_out,
+ input phy_init_done,
+ output app_af_wren,
+ output [2:0] app_af_cmd,
+ output [30:0] app_af_addr,
+ output app_wdf_wren,
+ output [APPDATA_WIDTH-1:0] app_wdf_data,
+ output [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
+ output error,
+ output error_cmp
+ );
+
+ localparam BURST_LEN_DIV2 = BURST_LEN/2;
+
+ localparam TB_IDLE = 3'b000;
+ localparam TB_WRITE = 3'b001;
+ localparam TB_READ = 3'b010;
+
+ wire app_af_afull_r ;
+ wire app_af_afull_r1 ;
+ wire app_af_afull_r2;
+ reg app_af_not_afull_r;
+ wire [APPDATA_WIDTH-1:0] app_cmp_data;
+ wire app_wdf_afull_r;
+ wire app_wdf_afull_r1 ;
+ wire app_wdf_afull_r2;
+ reg app_wdf_not_afull_r ;
+ reg [2:0] burst_cnt;
+ reg phy_init_done_tb_r;
+ wire phy_init_done_r;
+ reg rst_r
+ /* synthesis syn_preserve = 1 */;
+ reg rst_r1
+ /* synthesis syn_maxfan = 10 */;
+ reg [2:0] state;
+ reg [3:0] state_cnt;
+ reg wr_addr_en ;
+ reg wr_data_en ;
+
+ // XST attributes for local reset "tree"
+ // synthesis attribute shreg_extract of rst_r is "no";
+ // synthesis attribute shreg_extract of rst_r1 is "no";
+ // synthesis attribute equivalent_register_removal of rst_r is "no"
+
+ //*****************************************************************
+
+ // local reset "tree" for controller logic only. Create this to ease timing
+ // on reset path. Prohibit equivalent register removal on RST_R to prevent
+ // "sharing" with other local reset trees (caution: make sure global fanout
+ // limit is set to larger than fanout on RST_R, otherwise SLICES will be
+ // used for fanout control on RST_R.
+ always @(posedge clk0) begin
+ rst_r <= rst0;
+ rst_r1 <= rst_r;
+ end
+
+ // Instantiate flops for timing.
+ FDRSE ff_af_afull_r
+ (
+ .Q (app_af_afull_r),
+ .C (clk0),
+ .CE (1'b1),
+ .D (app_af_afull),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ FDRSE ff_af_afull_r1
+ (
+ .Q (app_af_afull_r1),
+ .C (clk0),
+ .CE (1'b1),
+ .D (app_af_afull_r),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ FDRSE ff_af_afull_r2
+ (
+ .Q (app_af_afull_r2),
+ .C (clk0),
+ .CE (1'b1),
+ .D (app_af_afull_r1),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+
+ FDRSE ff_wdf_afull_r
+ (
+ .Q (app_wdf_afull_r),
+ .C (clk0),
+ .CE (1'b1),
+ .D (app_wdf_afull),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ FDRSE ff_wdf_afull_r1
+ (
+ .Q (app_wdf_afull_r1),
+ .C (clk0),
+ .CE (1'b1),
+ .D (app_wdf_afull_r),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ FDRSE ff_wdf_afull_r2
+ (
+ .Q (app_wdf_afull_r2),
+ .C (clk0),
+ .CE (1'b1),
+ .D (app_wdf_afull_r1),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ FDRSE ff_phy_init_done
+ (
+ .Q (phy_init_done_r),
+ .C (clk0),
+ .CE (1'b1),
+ .D (phy_init_done),
+ .R (1'b0),
+ .S (1'b0)
+ );
+
+ //***************************************************************************
+ // State Machine for writing to WRITE DATA & ADDRESS FIFOs
+ // state machine changed for low FIFO threshold values
+ //***************************************************************************
+
+ always @(posedge clk0) begin
+ if (rst_r1) begin
+ wr_data_en <= 1'bx;
+ wr_addr_en <= 1'bx;
+ state[2:0] <= TB_IDLE;
+ state_cnt <= 4'bxxxx;
+ app_af_not_afull_r <= 1'bx;
+ app_wdf_not_afull_r <= 1'bx;
+ burst_cnt <= 3'bxxx;
+ phy_init_done_tb_r <= 1'bx;
+ end else begin
+ wr_data_en <= 1'b0;
+ wr_addr_en <= 1'b0;
+ app_af_not_afull_r <= ~app_af_afull_r2;
+ app_wdf_not_afull_r <= ~app_wdf_afull_r2;
+ phy_init_done_tb_r <= phy_init_done_r;
+
+ case (state)
+ TB_IDLE: begin
+ state_cnt <= 4'd0;
+ burst_cnt <= BURST_LEN_DIV2 - 1;
+ // only start writing when initialization done
+ if (app_wdf_not_afull_r && app_af_not_afull_r && phy_init_done_tb_r)
+ state <= TB_WRITE;
+ end
+
+ TB_WRITE:
+ if (app_wdf_not_afull_r && app_af_not_afull_r) begin
+ wr_data_en <= 1'b1;
+ // When we're done with the current burst...
+ if (burst_cnt == 3'd0) begin
+ burst_cnt <= BURST_LEN_DIV2 - 1;
+ wr_addr_en <= 1'b1;
+ // Writes occurs in groups of 8 consecutive bursts. Once 8 writes
+ // have been issued, now issue the corresponding read back bursts
+ if (state_cnt == 4'd7) begin
+ state <= TB_READ;
+ state_cnt <= 4'd0;
+ end else
+ state_cnt <= state_cnt + 1;
+ end else
+ burst_cnt <= burst_cnt - 1;
+ end
+
+ TB_READ: begin
+ burst_cnt <= BURST_LEN_DIV2 - 1;
+ if (app_af_not_afull_r) begin
+ wr_addr_en <= 1'b1;
+ // if finished with all 8 reads, proceed to next 8 writes
+ if (state_cnt == 4'd7) begin
+ state <= TB_WRITE;
+ state_cnt <= 4'd0;
+ end else
+ state_cnt <= state_cnt + 1;
+ end
+ end
+ endcase
+ end
+ end
+
+ // Read data comparision
+ ddr2_tb_test_cmp #
+ (
+ .DQ_WIDTH (DQ_WIDTH),
+ .APPDATA_WIDTH (APPDATA_WIDTH),
+ .ECC_ENABLE (ECC_ENABLE)
+ )
+ u_tb_test_cmp
+ (
+ .clk (clk0),
+ .rst (rst0),
+ .phy_init_done (phy_init_done_tb_r),
+ .rd_data_valid (rd_data_valid),
+ .app_cmp_data (app_cmp_data),
+ .rd_data_fifo_in (rd_data_fifo_out),
+ .error (error),
+ .error_cmp (error_cmp)
+ );
+
+ // Command/Address and Write Data generation
+ ddr2_tb_test_gen #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .DM_WIDTH (DM_WIDTH),
+ .DQ_WIDTH (DQ_WIDTH),
+ .APPDATA_WIDTH (APPDATA_WIDTH),
+ .ECC_ENABLE (ECC_ENABLE),
+ .ROW_WIDTH (ROW_WIDTH)
+ )
+ u_tb_test_gen
+ (
+ .clk (clk0),
+ .rst (rst0),
+ .wr_addr_en (wr_addr_en),
+ .wr_data_en (wr_data_en),
+ .rd_data_valid (rd_data_valid),
+ .app_af_wren (app_af_wren),
+ .app_af_cmd (app_af_cmd),
+ .app_af_addr (app_af_addr),
+ .app_wdf_wren (app_wdf_wren),
+ .app_wdf_data (app_wdf_data),
+ .app_wdf_mask_data (app_wdf_mask_data),
+ .app_cmp_data (app_cmp_data)
+ );
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_gen.v
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_gen.v (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/sim/ddr2_tb_test_gen.v (revision 3)
@@ -0,0 +1,128 @@
+//*****************************************************************************
+// DISCLAIMER OF LIABILITY
+//
+// This file contains proprietary and confidential information of
+// Xilinx, Inc. ("Xilinx"), that is distributed under a license
+// from Xilinx, and may be used, copied and/or disclosed only
+// pursuant to the terms of a valid license agreement with Xilinx.
+//
+// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
+// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
+// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
+// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
+// does not warrant that functions included in the Materials will
+// meet the requirements of Licensee, or that the operation of the
+// Materials will be uninterrupted or error-free, or that defects
+// in the Materials will be corrected. Furthermore, Xilinx does
+// not warrant or make any representations regarding use, or the
+// results of the use, of the Materials in terms of correctness,
+// accuracy, reliability or otherwise.
+//
+// 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.
+//
+// Copyright 2006, 2007 Xilinx, Inc.
+// All rights reserved.
+//
+// This disclaimer and copyright notice must be retained as part
+// of this file at all times.
+//*****************************************************************************
+// ____ ____
+// / /\/ /
+// /___/ \ / Vendor: Xilinx
+// \ \ \/ Version: 3.6.1
+// \ \ Application: MIG
+// / / Filename: ddr2_tb_test_gen.v
+// /___/ /\ Date Last Modified: $Date: 2010/11/26 18:26:02 $
+// \ \ / \ Date Created: Fri Sep 01 2006
+// \___\/\___\
+//
+//Device: Virtex-5
+//Design Name: DDR2
+//Purpose:
+// This module instantiates the addr_gen and the data_gen modules. It takes
+// the user data stored in internal FIFOs and gives the data that is to be
+// compared with the read data
+//Reference:
+//Revision History:
+//*****************************************************************************
+
+`timescale 1ns/1ps
+
+module ddr2_tb_test_gen #
+ (
+ // Following parameters are for 72-bit RDIMM design (for ML561 Reference
+ // board design). Actual values may be different. Actual parameters values
+ // are passed from design top module MEMCtrl module. Please refer to
+ // the MEMCtrl module for actual values.
+ parameter BANK_WIDTH = 2,
+ parameter COL_WIDTH = 10,
+ parameter DM_WIDTH = 9,
+ parameter DQ_WIDTH = 72,
+ parameter APPDATA_WIDTH = 144,
+ parameter ECC_ENABLE = 0,
+ parameter ROW_WIDTH = 14
+ )
+ (
+ input clk,
+ input rst,
+ input wr_addr_en,
+ input wr_data_en,
+ input rd_data_valid,
+ output app_af_wren,
+ output [2:0] app_af_cmd,
+ output [30:0] app_af_addr,
+ output app_wdf_wren,
+ output [APPDATA_WIDTH-1:0] app_wdf_data,
+ output [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data,
+ output [APPDATA_WIDTH-1:0] app_cmp_data
+ );
+
+ //***************************************************************************
+
+ ddr2_tb_test_addr_gen #
+ (
+ .BANK_WIDTH (BANK_WIDTH),
+ .COL_WIDTH (COL_WIDTH),
+ .ROW_WIDTH (ROW_WIDTH)
+ )
+ u_addr_gen
+ (
+ .clk (clk),
+ .rst (rst),
+ .wr_addr_en (wr_addr_en),
+ .app_af_cmd (app_af_cmd),
+ .app_af_addr (app_af_addr),
+ .app_af_wren (app_af_wren)
+ );
+
+ ddr2_tb_test_data_gen #
+ (
+ .DM_WIDTH (DM_WIDTH),
+ .DQ_WIDTH (DQ_WIDTH),
+ .APPDATA_WIDTH (APPDATA_WIDTH),
+ .ECC_ENABLE (ECC_ENABLE)
+ )
+ u_data_gen
+ (
+ .clk (clk),
+ .rst (rst),
+ .wr_data_en (wr_data_en),
+ .rd_data_valid (rd_data_valid),
+ .app_wdf_wren (app_wdf_wren),
+ .app_wdf_data (app_wdf_data),
+ .app_wdf_mask_data (app_wdf_mask_data),
+ .app_cmp_data (app_cmp_data)
+ );
+
+endmodule
Index: rtl/ipcore_dir/MEMCtrl/user_design/sim
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design/sim (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design/sim (revision 3)
rtl/ipcore_dir/MEMCtrl/user_design/sim
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: rtl/ipcore_dir/MEMCtrl/user_design
===================================================================
--- rtl/ipcore_dir/MEMCtrl/user_design (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl/user_design (revision 3)
rtl/ipcore_dir/MEMCtrl/user_design
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: rtl/ipcore_dir/MEMCtrl
===================================================================
--- rtl/ipcore_dir/MEMCtrl (nonexistent)
+++ rtl/ipcore_dir/MEMCtrl (revision 3)
rtl/ipcore_dir/MEMCtrl
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: rtl/ipcore_dir
===================================================================
--- rtl/ipcore_dir (nonexistent)
+++ rtl/ipcore_dir (revision 3)
rtl/ipcore_dir
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: rtl/debounceRst.v
===================================================================
--- rtl/debounceRst.v (revision 2)
+++ rtl/debounceRst.v (revision 3)
@@ -37,7 +37,7 @@
wire async_rst, PLLRst, rst_edge, start_up_rst;
- // --4-bit Shift Register For resetting the DCM on startup (Xilinx Answer Record: 14425)
+ // --4-bit Shift Register For resetting the PLL
//--Asserts Start_Up_Rst for 4 clock periods
SRL16E #(
@@ -65,8 +65,8 @@
//----------------------------------------------------------------------------------
//-- Reset with take-off and landing
- //-- delay 95 cc = RST_SYNC_NUM - 4 reset
- //-- then keep it active for 3 cc (as long as one of RstQ(RST_SYNC_NUM-2), RstQ(RST_SYNC_NUM-3) or RstQ(RST_SYNC_NUM-4) is 0)
+ //-- delay 95 cc = DELAY_CC - 4 reset
+ //-- then keep it active for 3 cc (as long as one of rst_debounce_delay_loop[DELAY_CC-2], rst_debounce_delay_loop[DELAY_CC-3] or rst_debounce_delay_loop[DELAY_CC-4] is 0)
//----------------------------------------------------------------------------------
always @(posedge clk)
begin
@@ -79,11 +79,11 @@
assign int_rst = ~PLLLocked;
- //decrement counter for 100 cc then RstD(RstD'high) becomes 0
+ //decrement counter for 100 cc then rst_cnt_delay[BITS_DELAY_CC-1] becomes 0
always @(posedge clk)
begin
if (int_rst)
- rst_cnt_delay <= 228;//DELAY_CC + {1'b1, {(BITS_DELAY_CC-2){1'b0}}};//{1'b1, (BITS_DELAY_CC-1)'dDELAY_CC};
+ rst_cnt_delay <= 228;//DELAY_CC + {1'b1, {(BITS_DELAY_CC-2){1'b0}}};
else
if (rst_cnt_delay[BITS_DELAY_CC-1])
rst_cnt_delay <= rst_cnt_delay - 1;
/rtl/ddr2_adr_data_gen.v
0,0 → 1,159
//***************************************************************************** |
// Company: UPT |
// Engineer: Oana Boncalo & Alexandru Amaricai |
// |
// Create Date: 10:23:39 11/26/2012 |
// Design Name: |
// Module Name: DDR2 user IF address and data generation |
// Project Name: |
// Target Devices: |
// Tool versions: |
//Device: Virtex-5 |
//Purpose: |
// This module instantiates the addr_gen and the data_gen modules. It takes |
// the user data stored in internal FIFOs and gives the data that is to be |
// compared with the read data |
//Reference: |
//Revision History: |
//***************************************************************************** |
|
`timescale 1ns/1ps |
|
module ddr2_adr_data_gen # |
( |
// Following parameters are for 72-bit RDIMM design (for ML561 Reference |
// board design). Actual values may be different. Actual parameters values |
// are passed from design top module MEMCtrl module. Please refer to |
// the MEMCtrl module for actual values. |
parameter BANK_WIDTH = 2, |
parameter COL_WIDTH = 10, |
parameter DM_WIDTH = 9, |
parameter DQ_WIDTH = 72, |
parameter APPDATA_WIDTH = 144, |
parameter ECC_ENABLE = 0, |
parameter ROW_WIDTH = 14 |
) |
( |
input clk, |
input rst, |
input wr_addr_en, |
input wr_data_en, |
input rd_op, |
input rd_data_valid, |
input [30:0] bus_if_addr, |
input [APPDATA_WIDTH-1:0] bus_if_wr_data, |
input [(APPDATA_WIDTH/8)-1:0] bus_if_wr_mask_data, |
output reg app_af_wren, |
output [2:0] app_af_cmd, |
output [30:0] app_af_addr, |
output app_wdf_wren, |
output [APPDATA_WIDTH-1:0] app_wdf_data, |
output [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data |
); |
|
//data |
localparam RD_IDLE_FIRST_DATA = 2'b00; |
localparam RD_SECOND_DATA = 2'b01; |
localparam RD_THIRD_DATA = 2'b10; |
localparam RD_FOURTH_DATA = 2'b11; |
|
//address |
reg wr_addr_en_r1; |
reg [2:0] af_cmd_r;//, af_cmd_r0, af_cmd_r1; |
reg af_wren_r; |
reg rst_r |
/* synthesis syn_preserve = 1 */; |
reg rst_r1 |
/* synthesis syn_maxfan = 10 */; |
reg [5:0] wr_addr_r; |
reg wr_addr_en_r0; |
|
//data |
reg [APPDATA_WIDTH-1:0] app_wdf_data_r; |
reg [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data_r; |
wire app_wdf_wren_r; |
reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_fall; |
reg [(APPDATA_WIDTH/2)-1:0] rd_data_pat_rise; |
reg [1:0] rd_state; |
wire [APPDATA_WIDTH-1:0] wr_data; |
reg wr_data_en_r; |
reg [(APPDATA_WIDTH/2)-1:0] wr_data_fall |
/* synthesis syn_maxfan = 2 */; |
reg [(APPDATA_WIDTH/2)-1:0] wr_data_rise |
/* synthesis syn_maxfan = 2 */; |
wire [(APPDATA_WIDTH/8)-1:0] wr_mask_data; |
|
//*************************************************************************** |
|
// local reset "tree" for controller logic only. Create this to ease timing |
// on reset path. Prohibit equivalent register removal on RST_R to prevent |
// "sharing" with other local reset trees (caution: make sure global fanout |
// limit is set to larger than fanout on RST_R, otherwise SLICES will be |
// used for fanout control on RST_R. |
always @(posedge clk) begin |
rst_r <= rst; |
rst_r1 <= rst_r; |
end |
// register backend enables / FIFO enables |
// write enable for Command/Address FIFO is generated 1 CC after WR_ADDR_EN |
always @(posedge clk) |
if (rst_r1) begin |
app_af_wren <= 1'b0; |
end else begin |
app_af_wren <= wr_addr_en; |
end |
|
always @ (posedge clk) |
if (rst_r1) |
wr_addr_r <= 0; |
else if (wr_addr_en && (rd_op == 1'b0)) |
wr_addr_r <= bus_if_addr; |
|
assign app_af_addr = wr_addr_r; |
assign app_af_cmd = af_cmd_r; |
|
always @ (posedge clk) |
begin |
af_cmd_r <= 0; |
if (rd_op) |
af_cmd_r <= 3'b001; |
end |
|
|
//data |
assign app_wdf_data = wr_data; |
assign app_wdf_mask_data = wr_mask_data; |
// inst ff for timing |
FDRSE ff_wdf_wren |
( |
.Q (app_wdf_wren), |
.C (clk), |
.CE (1'b1), |
.D (wr_data_en), |
.R (1'b0), |
.S (1'b0) |
); |
|
assign wr_data = {wr_data_fall, wr_data_rise}; |
assign wr_mask_data = bus_if_wr_mask_data; |
|
//data latching |
//synthesis attribute max_fanout of wr_data_fall is 2 |
//synthesis attribute max_fanout of wr_data_rise is 2 |
always @(posedge clk) |
begin |
if (rst_r1) |
begin |
wr_data_rise <= {(APPDATA_WIDTH/2){1'bx}}; |
wr_data_fall <= {(APPDATA_WIDTH/2){1'bx}}; |
end |
else |
if (wr_data_en) |
begin |
wr_data_rise <= bus_if_wr_data[(APPDATA_WIDTH/2)-1:0]; |
wr_data_fall <= bus_if_wr_data[APPDATA_WIDTH-1:(APPDATA_WIDTH/2)]; |
end |
end |
|
|
endmodule |
/rtl/ddr2_user_if_top.v
0,0 → 1,211
//***************************************************************************** |
// Company: UPT |
// Engineer: Oana Boncalo & Alexandru Amaricai |
// |
// Create Date: 10:23:39 11/26/2012 |
// Design Name: |
// Module Name: DDR2 user IF for Genesys board |
// Project Name: |
// Target Devices: |
// Tool versions: |
//Device: Virtex-5 |
//Reference: |
//Revision History: |
//***************************************************************************** |
|
`timescale 1ns/1ps |
|
module ddr2_user_if_top # |
( |
// Following parameters are for 72-bit RDIMM design (for ML561 Reference |
// board design). Actual values may be different. Actual parameters values |
// are passed from design top module MEMCtrl module. Please refer to |
// the MEMCtrl module for actual values. |
parameter BANK_WIDTH = 2, |
parameter COL_WIDTH = 10, |
parameter DM_WIDTH = 9, |
parameter DQ_WIDTH = 72, |
parameter ROW_WIDTH = 14, |
parameter APPDATA_WIDTH = 144, |
parameter ECC_ENABLE = 0, |
parameter BURST_LEN = 4 |
) |
( |
input clk0, |
input rst0, |
input app_af_afull, |
input app_wdf_afull, |
input rd_data_valid, |
input [APPDATA_WIDTH-1:0] rd_data_fifo_out, |
input phy_init_done, |
input rd_cmd, |
input wr_cmd, |
input [30:0] bus_if_addr, |
input [APPDATA_WIDTH-1:0] bus_if_wr_data, |
input [(APPDATA_WIDTH/8)-1:0] bus_if_wr_mask_data, |
output end_op, |
output req_wd, |
output app_af_wren, |
output [2:0] app_af_cmd, |
output [30:0] app_af_addr, |
output app_wdf_wren, |
output [APPDATA_WIDTH-1:0] app_wdf_data, |
output [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data, |
output error, |
output error_cmp |
); |
|
localparam BURST_LEN_DIV2 = BURST_LEN/2; |
|
localparam IDLE_CMD = 3'b000; |
localparam WRITE_CMD = 3'b001; |
localparam READ_CMD = 3'b010; |
|
reg app_af_not_afull_r; |
wire [APPDATA_WIDTH-1:0] app_cmp_data; |
reg app_wdf_not_afull_r ; |
reg [2:0] burst_cnt; |
reg phy_init_done_tb_r; |
wire phy_init_done_r; |
reg rst_r |
/* synthesis syn_preserve = 1 */; |
reg rst_r1 |
/* synthesis syn_maxfan = 10 */; |
reg [2:0] state; |
reg [3:0] state_cnt; |
reg wr_addr_en ; |
reg wr_data_en ; |
reg rd_op; |
reg end_op_r; |
|
// XST attributes for local reset "tree" |
// synthesis attribute shreg_extract of rst_r is "no"; |
// synthesis attribute shreg_extract of rst_r1 is "no"; |
// synthesis attribute equivalent_register_removal of rst_r is "no" |
|
//***************************************************************** |
|
// local reset "tree" for controller logic only. Create this to ease timing |
// on reset path. Prohibit equivalent register removal on RST_R to prevent |
// "sharing" with other local reset trees (caution: make sure global fanout |
// limit is set to larger than fanout on RST_R, otherwise SLICES will be |
// used for fanout control on RST_R. |
always @(posedge clk0) begin |
rst_r <= rst0; |
rst_r1 <= rst_r; |
end |
|
// Instantiate flops for timing. |
FDRSE ff_phy_init_done |
( |
.Q (phy_init_done_r), |
.C (clk0), |
.CE (1'b1), |
.D (phy_init_done), |
.R (1'b0), |
.S (1'b0) |
); |
|
assign end_op = end_op_r; |
//*************************************************************************** |
// State Machine for writing to WRITE DATA & ADDRESS FIFOs |
// state machine changed for low FIFO threshold values |
//*************************************************************************** |
|
always @(posedge clk0) begin |
if (rst_r1) begin |
wr_data_en <= 1'bx; |
wr_addr_en <= 1'bx; |
state[2:0] <= IDLE_CMD; |
state_cnt <= 4'bxxxx; |
app_af_not_afull_r <= 1'bx; |
app_wdf_not_afull_r <= 1'bx; |
burst_cnt <= 3'bxxx; |
phy_init_done_tb_r <= 1'bx; |
rd_op <= 1'bx; |
end_op_r <= 1'bx; |
end else begin |
wr_data_en <= 1'b0; |
wr_addr_en <= 1'b0; |
rd_op <= 1'b0; |
end_op_r <= 1'b0; |
app_af_not_afull_r <= ~app_af_afull; |
app_wdf_not_afull_r <= ~app_wdf_afull; |
phy_init_done_tb_r <= phy_init_done_r; |
|
case (state) |
IDLE_CMD: begin |
state_cnt <= 4'd0; |
burst_cnt <= BURST_LEN_DIV2 - 1; |
end_op_r <= 1'b0; |
// only start writing when initialization done |
if (app_wdf_not_afull_r && app_af_not_afull_r && phy_init_done_tb_r) |
begin |
if (rd_cmd) |
state <= READ_CMD; |
if (wr_cmd) |
state <= WRITE_CMD; |
end |
end |
|
WRITE_CMD: |
if (app_wdf_not_afull_r && app_af_not_afull_r) |
begin |
wr_data_en <= 1'b1; |
// When we're done with the current burst... |
if (burst_cnt == 3'd0) |
begin |
wr_addr_en <= 1'b1; |
state <= IDLE_CMD; |
end_op_r <= 1'b1; |
end |
else |
burst_cnt <= burst_cnt - 1; |
end |
|
READ_CMD: begin |
burst_cnt <= BURST_LEN_DIV2 - 1; |
if (app_af_not_afull_r) |
begin |
wr_addr_en <= 1'b1; |
rd_op <= 1'b1; |
state <= IDLE_CMD; |
end_op_r <= 1'b1; |
end |
end |
endcase |
end |
end |
assign req_wd = (!wr_addr_en && wr_data_en)? 1'b1:1'b0; |
|
// Command/Address and Write Data generation |
ddr2_adr_data_gen # |
( |
.BANK_WIDTH (BANK_WIDTH), |
.COL_WIDTH (COL_WIDTH), |
.DM_WIDTH (DM_WIDTH), |
.DQ_WIDTH (DQ_WIDTH), |
.APPDATA_WIDTH (APPDATA_WIDTH), |
.ECC_ENABLE (ECC_ENABLE), |
.ROW_WIDTH (ROW_WIDTH) |
) |
u_adr_data_gen |
( |
.clk (clk0), |
.rst (rst0), |
.wr_addr_en (wr_addr_en), |
.wr_data_en (wr_data_en), |
.rd_op (rd_op), |
.rd_data_valid (rd_data_valid), |
.bus_if_addr (bus_if_addr), |
.app_af_wren (app_af_wren), |
.bus_if_wr_mask_data(bus_if_wr_mask_data), |
.bus_if_wr_data (bus_if_wr_data), |
.app_af_cmd (app_af_cmd), |
.app_af_addr (app_af_addr), |
.app_wdf_wren (app_wdf_wren), |
.app_wdf_data (app_wdf_data), |
.app_wdf_mask_data (app_wdf_mask_data) |
); |
|
endmodule |
/README.txt
0,0 → 1,84
genesys_ddr2: DDR2 memory controller for Digilent Genesys board |
=================================================== |
|
|
What is this stuff? |
================== |
|
This is DDR2 memory controller for Digilent Genesys Board with wishbone slave interface and synthesizable test bench. |
|
This IP is made-of several design files structured in the following directories: |
- rtl: the user interface for the DDR2, the wishbone interface, external PLL clock generator, reset button debouncer as well as global reset generator |
- rtl\ipcore_dir\MemCtrl: the DDR2 memory controller files generated by Xilinx MIG tool |
- par: ucf file used for testing the synthesisable bench. The ucf file contains the memory pin placement as well as a reset pin connected to button from LOC = "G7" |
- bench: synthesisable test files - top level module (test_DDR2_wb.v) and simple wishbone master mock that generates burst transactions for write followed by a read from the same address |
|
|
|
DDR2 IP core |
============== |
|
DDR2_Mem.v - top level DDR2 memory wishbone compatible if module |
| |
| |
--- ddr2_user_if_top.v - user interface top module: receives write/read commands from bus interface module |
generates FIFO wr commands for address and data |
|
| |
| |
--- ddr2_adr_data_gen.v : latches commands data byte enable rd/wr data to/from FIFOS |
| |
| |
--- clkGenPLL.v - generates clk signals for memory controller: clk0_125MHz, clk0Phase90, clk0Div2, clk200MHz as well as clkTFT10MHz and clkTFT10_180 for VMODTFT |
| |
| |
--- DDR2_mem_wb_if.v - wishbone slave interface: generates rd/wr command requests for user interface (ddr2_user_if_top.v) module |
| |
| |
--- debounceRst.v - global reset generator & reset button debouncer |
| |
| |
--- rtl\ipcore_dir\MemCtrl - files generated using Xilinx MIG Version: 3.6.1. Parameters: Bust length: 4, Data size: 64. |
|
|
|
Synthesizable bench |
==================== |
test_DDR2_wb.v - top level module FPGA proven |
| |
| |
--- DDR2_Mem.v -top level DDR2 memory wishbone compatible if module |
| |
| |
--- wishbone_master_mock - master wishbone interface connected to the memory slave interface; it generates a write burst followed by a read burst transaction |
|
|
Tools used |
========= |
|
Xilinx ISE 14.4, Chipscope courtesy of Xilinx through Xilinx University Program. |
|
|
Bench test |
============== |
|
FPGA proven toplevel module - top level module: test_DDR2_wb.v verified using Chipscope. |
|
|
Known issues |
============= |
Attempt to move the PLL instance one level up in the hierarchy to test_DDR2_wb (test_DDR2_wb.v) resulted in the FPGA design not working. |
|
|
|
genesys_ddr2 and OpenCores |
========================== |
|
This project is licensed under the GNU Public License version 3. |
|
|
About the same idea as with GNU project except we want free and open source |
IP (intellectual property) cores. We design open source, synthesizable |
cores. |
|
For more information visit us at http://www.opencores.org. |