/******************************************************************************* * Module: ddr3_wrap * Date:2015-04-20 * Author: Andrey Filippov * Description: ddr3 model wrapper to include delays matching hardware * * Copyright (c) 2015 Elphel, Inc. * ddr3_wrap.v is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ddr3_wrap.v is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . *******************************************************************************/ //`timescale 1ns/1ps `timescale 1ps / 1ps module ddr3_wrap#( parameter ADDRESS_NUMBER = 15, parameter TRISTATE_DELAY_CLK = 4'h2, parameter TRISTATE_DELAY = 0, parameter CLK_DELAY = 1500, parameter CMDA_DELAY = 1500, parameter DQS_IN_DELAY = 1500, parameter DQ_IN_DELAY = 1500, parameter DQS_OUT_DELAY = 1500, parameter DQ_OUT_DELAY = 1500 )( input mclk, input [1:0] dq_tri, input [1:0] dqs_tri, input SDRST, // DDR3 reset (active low) input SDCLK, // DDR3 clock differential output, positive input SDNCLK,// DDR3 clock differential output, negative input [ADDRESS_NUMBER-1:0] SDA, // output address ports (14:0) for 4Gb device input [2:0] SDBA, // output bank address ports input SDWE, // output WE port input SDRAS, // output RAS port input SDCAS, // output CAS port input SDCKE, // output Clock Enable port input SDODT, // output ODT port inout [15:0] SDD, // DQ I/O pads input SDDML, // LDM I/O pad (actually only output) inout DQSL, // LDQS I/O pad inout NDQSL, // ~LDQS I/O pad input SDDMU, // UDM I/O pad (actually only output) inout DQSU, // UDQS I/O pad inout NDQSU //, ); localparam CLK_DELAY_H = CLK_DELAY/4; localparam CMDA_DELAY_H = CMDA_DELAY/4; localparam DQS_IN_DELAY_H = DQS_IN_DELAY/4; localparam DQ_IN_DELAY_H = DQ_IN_DELAY/4; localparam DQS_OUT_DELAY_H = DQS_OUT_DELAY/4; localparam DQ_OUT_DELAY_H = DQ_OUT_DELAY/4; wire #(CLK_DELAY_H) SDCLK_H1 = SDCLK; wire #(CLK_DELAY_H) SDNCLK_H1 = SDNCLK; wire #(CMDA_DELAY_H) SDRST_H1 = SDRST; wire [ADDRESS_NUMBER-1:0] #(CMDA_DELAY_H) SDA_H1 = SDA; wire [2:0] #(CMDA_DELAY_H) SDBA_H1 = SDBA; wire #(CMDA_DELAY_H) SDWE_H1 = SDWE; wire #(CMDA_DELAY_H) SDRAS_H1 = SDRAS; wire #(CMDA_DELAY_H) SDCAS_H1 = SDCAS; wire #(CMDA_DELAY_H) SDCKE_H1 = SDCKE; wire #(CMDA_DELAY_H) SDODT_H1 = SDODT; wire #(CLK_DELAY_H) SDCLK_H2 = SDCLK_H1; wire #(CLK_DELAY_H) SDNCLK_H2 = SDNCLK_H1; wire #(CMDA_DELAY_H) SDRST_H2 = SDRST_H1; wire [ADDRESS_NUMBER-1:0] #(CMDA_DELAY_H) SDA_H2 = SDA_H1; wire [2:0] #(CMDA_DELAY_H) SDBA_H2 = SDBA_H1; wire #(CMDA_DELAY_H) SDWE_H2 = SDWE_H1; wire #(CMDA_DELAY_H) SDRAS_H2 = SDRAS_H1; wire #(CMDA_DELAY_H) SDCAS_H2 = SDCAS_H1; wire #(CMDA_DELAY_H) SDCKE_H2 = SDCKE_H1; wire #(CMDA_DELAY_H) SDODT_H2 = SDODT_H1; wire #(CLK_DELAY_H) SDCLK_H3 = SDCLK_H2; wire #(CLK_DELAY_H) SDNCLK_H3 = SDNCLK_H2; wire #(CMDA_DELAY_H) SDRST_H3 = SDRST_H2; wire [ADDRESS_NUMBER-1:0] #(CMDA_DELAY_H) SDA_H3 = SDA_H2; wire [2:0] #(CMDA_DELAY_H) SDBA_H3 = SDBA_H2; wire #(CMDA_DELAY_H) SDWE_H3 = SDWE_H2; wire #(CMDA_DELAY_H) SDRAS_H3 = SDRAS_H2; wire #(CMDA_DELAY_H) SDCAS_H3 = SDCAS_H2; wire #(CMDA_DELAY_H) SDCKE_H3 = SDCKE_H2; wire #(CMDA_DELAY_H) SDODT_H3= SDODT_H2; wire #(CLK_DELAY_H) SDCLK_D = SDCLK_H3; wire #(CLK_DELAY_H) SDNCLK_D = SDNCLK_H3; wire #(CMDA_DELAY_H) SDRST_D = SDRST_H3; wire [ADDRESS_NUMBER-1:0] #(CMDA_DELAY_H) SDA_D = SDA_H3; wire [2:0] #(CMDA_DELAY_H) SDBA_D = SDBA_H3; wire #(CMDA_DELAY_H) SDWE_D = SDWE_H3; wire #(CMDA_DELAY_H) SDRAS_D = SDRAS_H3; wire #(CMDA_DELAY_H) SDCAS_D = SDCAS_H3; wire #(CMDA_DELAY_H) SDCKE_D = SDCKE_H3; wire #(CMDA_DELAY_H) SDODT_D = SDODT_H3; wire [1:0] en_dq_dl; wire [1:0] en_dqs_dl; wire [1:0] #(TRISTATE_DELAY) en_dq_d0 = en_dq_dl; wire [1:0] #(TRISTATE_DELAY) en_dqs_d0 = en_dqs_dl; wire [1:0] #(DQ_OUT_DELAY_H) en_dq_d1=en_dq_d0; wire [1:0] #(DQ_OUT_DELAY_H) en_dqs_d1=en_dqs_d0; wire [1:0] #(DQ_OUT_DELAY_H) en_dq_d2=en_dq_d1; wire [1:0] #(DQ_OUT_DELAY_H) en_dqs_d2=en_dqs_d1; wire [1:0] #(DQ_IN_DELAY_H) en_dq_d3=en_dq_d2; wire [1:0] #(DQ_IN_DELAY_H) en_dqs_d3=en_dqs_d2; wire [1:0] #(DQ_OUT_DELAY_H) en_dq_d4=en_dq_d3; wire [1:0] #(DQ_OUT_DELAY_H) en_dqs_d4=en_dqs_d3; wire [1:0] #(DQ_OUT_DELAY_H) en_dq_d5=en_dq_d4; wire [1:0] #(DQ_OUT_DELAY_H) en_dqs_d5=en_dqs_d4; wire [1:0] #(DQ_IN_DELAY_H) en_dq_d6=en_dq_d5; wire [1:0] #(DQ_IN_DELAY_H) en_dqs_d6=en_dqs_d5; wire [1:0] #(DQ_IN_DELAY_H) en_dq_d7=en_dq_d6; wire [1:0] #(DQ_IN_DELAY_H) en_dqs_d7=en_dqs_d6; // wire [1:0] en_dq_out=en_dq_d2; // wire [1:0] en_dqs_out=en_dqs_d2; wire [1:0] en_dq_out=en_dq_d3; wire [1:0] en_dqs_out=en_dqs_d3; // wire [1:0] en_dq_in= ~en_dq_d0 & ~en_dq_d1 & ~en_dq_d2 & ~en_dq_d3 & ~en_dq_d4; // wire [1:0] en_dqs_in=~en_dqs_d0 & ~en_dqs_d1 & ~en_dqs_d2 & ~en_dqs_d3 & ~en_dqs_d4; wire [1:0] en_dq_in= ~en_dq_d0 & ~en_dq_d1 & ~en_dq_d2 & ~en_dq_d3 & ~en_dq_d4 & ~en_dq_d5 & ~en_dq_d6 & ~en_dq_d7; wire [1:0] en_dqs_in=~en_dqs_d0 & ~en_dqs_d1 & ~en_dqs_d2 & ~en_dqs_d3 & ~en_dqs_d4 & ~en_dqs_d5 & ~en_dqs_d6 & ~en_dqs_d7; /* Instance template for module dly_16 */ dly_16 #( .WIDTH(4) ) dly_16_i ( .clk (mclk), .rst (~SDRST), .dly (TRISTATE_DELAY_CLK), .din ({~dqs_tri,~dq_tri}), .dout ({en_dqs_dl,en_dq_dl}) ); wire [15:0] SDD_H1; wire SDDML_H1; wire SDDMU_H1; wire DQSL_H1; wire NDQSL_H1; wire DQSU_H1; wire NDQSU_H1; wire [15:0] SDD_H2; wire SDDML_H2; wire SDDMU_H2; wire DQSL_H2; wire NDQSL_H2; wire DQSU_H2; wire NDQSU_H2; wire [15:0] SDD_H3; wire SDDML_H3; wire SDDMU_H3; wire DQSL_H3; wire NDQSL_H3; wire DQSU_H3; wire NDQSU_H3; wire [15:0] SDD_D; wire SDDML_D; wire SDDMU_D; wire DQSL_D; wire NDQSL_D; wire DQSU_D; wire NDQSU_D; wire [15:0] SDD_DH1; wire DQSL_DH1; wire NDQSL_DH1; wire DQSU_DH1; wire NDQSU_DH1; wire [15:0] SDD_DH2; wire DQSL_DH2; wire NDQSL_DH2; wire DQSU_DH2; wire NDQSU_DH2; wire [15:0] SDD_DH3; wire DQSL_DH3; wire NDQSL_DH3; wire DQSU_DH3; wire NDQSU_DH3; assign #(DQ_OUT_DELAY_H) SDD_H1[ 7:0] = SDD[7:0]; assign #(DQ_OUT_DELAY_H) SDD_H1[15:8] = SDD[15:8]; assign #(DQ_OUT_DELAY_H) SDD_H2[ 7:0] = SDD_H1[7:0]; assign #(DQ_OUT_DELAY_H) SDD_H2[15:8] = SDD_H1[15:8]; assign #(DQ_OUT_DELAY_H) SDD_H3[ 7:0] = SDD_H2[7:0]; assign #(DQ_OUT_DELAY_H) SDD_H3[15:8] = SDD_H2[15:8]; assign #(DQ_OUT_DELAY_H) SDD_D[ 7:0] = en_dq_out[0]? SDD_H3[7:0]: 8'bz; assign #(DQ_OUT_DELAY_H) SDD_D[15:8] = en_dq_out[1]? SDD_H3[15:8]:8'bz; assign #(DQ_OUT_DELAY_H) SDDML_H1 = SDDML; assign #(DQ_OUT_DELAY_H) SDDMU_H1 = SDDMU; assign #(DQ_OUT_DELAY_H) SDDML_H2 = SDDML_H1; assign #(DQ_OUT_DELAY_H) SDDMU_H2 = SDDMU_H1; assign #(DQ_OUT_DELAY_H) SDDML_H3 = SDDML_H2; assign #(DQ_OUT_DELAY_H) SDDMU_H3 = SDDMU_H2; assign #(DQ_OUT_DELAY_H) SDDML_D = en_dq_out[0]? SDDML_H3: 1'bz; assign #(DQ_OUT_DELAY_H) SDDMU_D = en_dq_out[1]? SDDMU_H3: 1'bz; assign #(DQ_IN_DELAY_H) SDD_DH1 [ 7:0] = SDD_D[7:0]; assign #(DQ_IN_DELAY_H) SDD_DH1 [15:8] = SDD_D[15:8]; assign #(DQ_IN_DELAY_H) SDD_DH2 [ 7:0] = SDD_DH1[7:0]; assign #(DQ_IN_DELAY_H) SDD_DH2 [15:8] = SDD_DH1[15:8]; assign #(DQ_IN_DELAY_H) SDD_DH3 [ 7:0] = SDD_DH2[7:0]; assign #(DQ_IN_DELAY_H) SDD_DH3 [15:8] = SDD_DH2[15:8]; assign #(DQ_IN_DELAY_H) SDD [ 7:0] = en_dq_in[0]? SDD_DH3[7:0]:8'bz; assign #(DQ_IN_DELAY_H) SDD [15:8] = en_dq_in[1]? SDD_DH3[15:8]:8'bz; assign #(DQS_OUT_DELAY_H) DQSL_H1 = DQSL; assign #(DQS_OUT_DELAY_H) NDQSL_H1 = NDQSL; assign #(DQS_OUT_DELAY_H) DQSU_H1 = DQSU; assign #(DQS_OUT_DELAY_H) NDQSU_H1 = NDQSU; assign #(DQS_OUT_DELAY_H) DQSL_H2 = DQSL_H1; assign #(DQS_OUT_DELAY_H) NDQSL_H2 = NDQSL_H1; assign #(DQS_OUT_DELAY_H) DQSU_H2 = DQSU_H1; assign #(DQS_OUT_DELAY_H) NDQSU_H2 = NDQSU_H1; assign #(DQS_OUT_DELAY_H) DQSL_H3 = DQSL_H2; assign #(DQS_OUT_DELAY_H) NDQSL_H3 = NDQSL_H2; assign #(DQS_OUT_DELAY_H) DQSU_H3 = DQSU_H2; assign #(DQS_OUT_DELAY_H) NDQSU_H3 = NDQSU_H2; assign #(DQS_OUT_DELAY_H) DQSL_D = en_dqs_out[0]? DQSL_H3: 1'bz; assign #(DQS_OUT_DELAY_H) NDQSL_D = en_dqs_out[0]? NDQSL_H3: 1'bz; assign #(DQS_OUT_DELAY_H) DQSU_D = en_dqs_out[1]? DQSU_H3: 1'bz; assign #(DQS_OUT_DELAY_H) NDQSU_D = en_dqs_out[1]? NDQSU_H3: 1'bz; assign #(DQS_IN_DELAY_H) DQSL_DH1 = DQSL_D; assign #(DQS_IN_DELAY_H) NDQSL_DH1 = NDQSL_D; assign #(DQS_IN_DELAY_H) DQSU_DH1 = DQSU_D; assign #(DQS_IN_DELAY_H) NDQSU_DH1 = NDQSU_D; assign #(DQS_IN_DELAY_H) DQSL_DH2 = DQSL_DH1; assign #(DQS_IN_DELAY_H) NDQSL_DH2 = NDQSL_DH1; assign #(DQS_IN_DELAY_H) DQSU_DH2 = DQSU_DH1; assign #(DQS_IN_DELAY_H) NDQSU_DH2 = NDQSU_DH1; assign #(DQS_IN_DELAY_H) DQSL_DH3 = DQSL_DH2; assign #(DQS_IN_DELAY_H) NDQSL_DH3 = NDQSL_DH2; assign #(DQS_IN_DELAY_H) DQSU_DH3 = DQSU_DH2; assign #(DQS_IN_DELAY_H) NDQSU_DH3 = NDQSU_DH2; assign #(DQS_IN_DELAY_H) DQSL = en_dqs_in[0]? DQSL_DH3: 1'bz; assign #(DQS_IN_DELAY_H) NDQSL = en_dqs_in[0]? NDQSL_DH3: 1'bz; assign #(DQS_IN_DELAY_H) DQSU = en_dqs_in[1]? DQSU_DH3: 1'bz; assign #(DQS_IN_DELAY_H) NDQSU = en_dqs_in[1]? NDQSU_DH3: 1'bz; ddr3 /*#( .TCK_MIN (2500), .TJIT_PER (100), .TJIT_CC (200), .TERR_2PER (147), .TERR_3PER (175), .TERR_4PER (194), .TERR_5PER (209), .TERR_6PER (222), .TERR_7PER (232), .TERR_8PER (241), .TERR_9PER (249), .TERR_10PER (257), .TERR_11PER (263), .TERR_12PER (269), .TDS (125), .TDH (150), .TDQSQ (200), .TDQSS (0.25), .TDSS (0.20), .TDSH (0.20), .TDQSCK (400), .TQSH (0.38), .TQSL (0.38), .TDIPW (600), .TIPW (900), .TIS (350), .TIH (275), .TRAS_MIN (37500), .TRC (52500), .TRCD (15000), .TRP (15000), .TXP (7500), .TCKE (7500), .TAON (400), .TWLS (325), .TWLH (325), .TWLO (9000), .TAA_MIN (15000), .CL_TIME (15000), .TDQSCK_DLLDIS (400), .TRRD (10000), .TFAW (40000), .CL_MIN (5), .CL_MAX (14), .AL_MIN (0), .AL_MAX (2), .WR_MIN (5), .WR_MAX (16), .BL_MIN (4), .BL_MAX (8), .CWL_MIN (5), .CWL_MAX (10), .TCK_MAX (3300), .TCH_AVG_MIN (0.47), .TCL_AVG_MIN (0.47), .TCH_AVG_MAX (0.53), .TCL_AVG_MAX (0.53), .TCH_ABS_MIN (0.43), .TCL_ABS_MIN (0.43), .TCKE_TCK (3), .TAA_MAX (20000), .TQH (0.38), .TRPRE (0.90), .TRPST (0.30), .TDQSH (0.45), .TDQSL (0.45), .TWPRE (0.90), .TWPST (0.30), .TCCD (4), .TCCD_DG (2), .TRAS_MAX (60e9), .TWR (15000), .TMRD (4), .TMOD (15000), .TMOD_TCK (12), .TRRD_TCK (4), .TRRD_DG (3000), .TRRD_DG_TCK (2), .TRTP (7500), .TRTP_TCK (4), .TWTR (7500), .TWTR_DG (3750), .TWTR_TCK (4), .TWTR_DG_TCK (2), .TDLLK (512), .TRFC_MIN (260000), .TRFC_MAX (70200000), .TXP_TCK (3), .TXPDLL (24000), .TXPDLL_TCK (10), .TACTPDEN (1), .TPRPDEN (1), .TREFPDEN (1), .TCPDED (1), .TPD_MAX (70200000), .TXPR (270000), .TXPR_TCK (5), .TXS (270000), .TXS_TCK (5), .TXSDLL (512), .TISXR (350), .TCKSRE (10000), .TCKSRE_TCK (5), .TCKSRX (10000), .TCKSRX_TCK (5), .TCKESR_TCK (4), .TAOF (0.7), .TAONPD (8500), .TAOFPD (8500), .ODTH4 (4), .ODTH8 (6), .TADC (0.7), .TWLMRD (40), .TWLDQSEN (25), .TWLOE (2000), .DM_BITS (2), .ADDR_BITS (15), .ROW_BITS (15), .COL_BITS (10), .DQ_BITS (16), .DQS_BITS (2), .BA_BITS (3), .MEM_BITS (10), .AP (10), .BC (12), .BL_BITS (3), .BO_BITS (2), .CS_BITS (1), .RANKS (1), .RZQ (240), .PRE_DEF_PAT (8'hAA), .STOP_ON_ERROR (1), .DEBUG (1), .BUS_DELAY (0), .RANDOM_OUT_DELAY (0), .RANDOM_SEED (31913), .RDQSEN_PRE (2), .RDQSEN_PST (1), .RDQS_PRE (2), .RDQS_PST (1), .RDQEN_PRE (0), .RDQEN_PST (0), .WDQS_PRE (2), .WDQS_PST (1), .check_strict_mrbits (1), .check_strict_timing (1), .feature_pasr (1), .feature_truebl4 (0), .feature_odt_hi (0), .PERTCKAVG (512), .LOAD_MODE (4'b0000), .REFRESH (4'b0001), .PRECHARGE (4'b0010), .ACTIVATE (4'b0011), .WRITE (4'b0100), .READ (4'b0101), .ZQ (4'b0110), .NOP (4'b0111), .PWR_DOWN (4'b1000), .SELF_REF (4'b1001), .RFF_BITS (128), .RFF_CHUNK (32), .SAME_BANK (2'd0), .DIFF_BANK (2'd1), .DIFF_GROUP (2'd2), .SIMUL_500US (5), .SIMUL_200US (2) ) */ ddr3_i ( .rst_n (SDRST_D), // input .ck (SDCLK_D), // input .ck_n (SDNCLK_D), // input .cke (SDCKE_D), // input .cs_n (1'b0), // input .ras_n (SDRAS_D), // input .cas_n (SDCAS_D), // input .we_n (SDWE_D), // input .dm_tdqs ({SDDMU_D,SDDML_D}), // inout[1:0] .ba (SDBA_D[2:0]), // input[2:0] .addr (SDA_D[14:0]), // input[14:0] .dq (SDD_D[15:0]), // inout[15:0] .dqs ({DQSU_D,DQSL_D}), // inout[1:0] .dqs_n ({NDQSU_D,NDQSL_D}), // inout[1:0] .tdqs_n (), // output[1:0] .odt (SDODT_D) // input ); endmodule