phy_cmd.v 25.7 KB
Newer Older
1 2 3 4 5 6 7
/*!
 * <b>Module:</b>phy_cmd
 * @file phy_cmd.v
 * @date 2014-05-15  
 * @author Andrey Filippov
 *
 * @brief Executes a stream of commands to DDR3 phy at 1/2 ddr3 clock, global
Andrey Filippov's avatar
Andrey Filippov committed
8 9
 * (also proveides r/w interface to the x64 external buffer)
 *
10 11 12 13
 * @copyright Copyright (c) 2014 Elphel, Inc.
 *
 * <b>License:</b>
 *
Andrey Filippov's avatar
Andrey Filippov committed
14 15 16 17 18 19 20 21 22 23 24 25
 * phy_cmd.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.
 *
 *  phy_cmd.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 <http://www.gnu.org/licenses/> .
26 27 28 29 30 31
 *
 * Additional permission under GNU GPL version 3 section 7:
 * If you modify this Program, or any covered work, by linking or combining it
 * with independent modules provided by the FPGA vendor only (this permission
 * does not extend to any 3-rd party modules, "soft cores" or macros) under
 * different license terms solely for the purpose of generating binary "bitstream"
32
 * files and/or simulating the code, the copyright holders of this Program give
33 34
 * you the right to distribute the covered work without those independent modules
 * as long as the source code for them is available from the FPGA vendor free of
Andrey Filippov's avatar
Andrey Filippov committed
35
 * charge, and there is no dependence on any encrypted modules for simulating of
36 37 38
 * the combined code. This permission applies to you if the distributed code
 * contains all the components and scripts required to completely simulate it
 * with at least one of the Free Software programs.
39
 */
Andrey Filippov's avatar
Andrey Filippov committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
`timescale 1ns/1ps

module  phy_cmd#(
    parameter ADDRESS_NUMBER = 15,
    parameter PHASE_WIDTH =     8,
    parameter SLEW_DQ =         "SLOW",
    parameter SLEW_DQS =        "SLOW",
    parameter SLEW_CMDA =       "SLOW",
    parameter SLEW_CLK =       "SLOW",
    parameter IBUF_LOW_PWR =    "TRUE",
    parameter real REFCLK_FREQUENCY = 300.0,
    parameter HIGH_PERFORMANCE_MODE = "FALSE",
    parameter CLKIN_PERIOD          = 10, //ns >1.25, 600<Fvco<1200
    parameter CLKFBOUT_MULT =       8, // Fvco=Fclkin*CLKFBOUT_MULT_F/DIVCLK_DIVIDE, Fout=Fvco/CLKOUT#_DIVIDE
    parameter DIVCLK_DIVIDE=        1,
55
    parameter CLKFBOUT_USE_FINE_PS= 1, // 0 - old, 1 - new 
Andrey Filippov's avatar
Andrey Filippov committed
56
    parameter CLKFBOUT_PHASE =      0.000,
57
    parameter SDCLK_PHASE =         0.000,
Andrey Filippov's avatar
Andrey Filippov committed
58 59 60 61 62 63
    parameter CLK_PHASE =           0.000,
    parameter CLK_DIV_PHASE =       0.000,
    parameter MCLK_PHASE =          90.000,
    parameter REF_JITTER1 =         0.010,
    parameter SS_EN =              "FALSE",
    parameter SS_MODE =      "CENTER_HIGH",
64
    parameter SS_MOD_PERIOD =       10000,
65 66
    parameter CMD_PAUSE_BITS=       10, // numer of (address) bits to encode pause
    parameter CMD_DONE_BIT=         10  // bit number (address) to signal sequence done
Andrey Filippov's avatar
Andrey Filippov committed
67 68
)(
    // DDR3 interface
69
    output                       SDRST, // DDR3 reset (active low)
Andrey Filippov's avatar
Andrey Filippov committed
70 71
    output                       SDCLK, // DDR3 clock differential output, positive
    output                       SDNCLK,// DDR3 clock differential output, negative
72
    output  [ADDRESS_NUMBER-1:0] SDA,   // output address ports (14:0) for 4Gb deviceencode_seq_word
Andrey Filippov's avatar
Andrey Filippov committed
73 74 75 76 77 78 79 80
    output                 [2:0] SDBA,  // output bank address ports
    output                       SDWE,  // output WE port
    output                       SDRAS, // output RAS port
    output                       SDCAS, // output CAS port
    output                       SDCKE, // output Clock Enable port
    output                       SDODT, // output ODT port

    inout                 [15:0] SDD,       // DQ  I/O pads
81
    output                       SDDML,      // LDM  I/O pad (actually only output)
Andrey Filippov's avatar
Andrey Filippov committed
82 83
    inout                        DQSL,     // LDQS I/O pad
    inout                        NDQSL,    // ~LDQS I/O pad
84
    output                       SDDMU,      // UDM  I/O pad (actually only output)
Andrey Filippov's avatar
Andrey Filippov committed
85 86 87 88 89
    inout                        DQSU,     // UDQS I/O pad
    inout                        NDQSU,    // ~UDQS I/O pad
// clocks, reset
    input                        clk_in,
    input                        rst_in,
90
    output                       mclk,     // global clock, half DDR3 clock, synchronizes all I/O through the command port
Andrey Filippov's avatar
Andrey Filippov committed
91
    input                        mrst,     // @posedge mclk synchronous reset - should not interrupt mclk generation
92
    input                        ref_clk,  // global clock for idelay_ctrl calibration
Andrey Filippov's avatar
Andrey Filippov committed
93
    output                       idelay_ctrl_reset,
Andrey Filippov's avatar
Andrey Filippov committed
94 95 96 97 98
// inteface to control I/O delays and mmcm
    input                  [7:0] dly_data, // delay value (3 LSB - fine delay)
    input                  [6:0] dly_addr, // select which delay to program
    input                        ld_delay, // load delay data to selected iodelayl (clk_div synchronous)
    input                        set,       // clk_div synchronous set all delays from previously loaded values
99 100 101 102 103 104 105 106 107 108 109 110
    output                       locked_mmcm,
    output                       locked_pll,
    output                       dly_ready,
    output                       dci_ready,

    output                       phy_locked_mmcm,
    output                       phy_locked_pll,
    output                       phy_dly_ready,
    output                       phy_dci_ready,
    
    output               [7:0]   tmp_debug,

Andrey Filippov's avatar
Andrey Filippov committed
111 112 113
    output                       ps_rdy,
    output     [PHASE_WIDTH-1:0] ps_out, 
// command port
114 115
    input                 [31:0] phy_cmd_word,
    output                       phy_cmd_nop,
116 117
    output                       phy_cmd_add_pause, // one pause cycle (for 8-bursts)
    input                        add_pause, // use previous command settings, just replace command with nop
118 119
    output  [CMD_PAUSE_BITS-1:0] pause_len,
    output                       sequence_done,
Andrey Filippov's avatar
Andrey Filippov committed
120 121 122 123
// external memory buffer (cs- channel select, high addresses- page addresses are decoded externally)
    output                [63:0] buf_wdata, // data to be written to the buffer (from DDR3), valid @ negedge mclk
    input                 [63:0] buf_rdata, // data read from the buffer (to DDR3)
    output                       buf_wr,    // write buffer (next cycle!)
124 125
    output                       buf_rd,    // read buffer  (ready next cycle)
    output                       buf_rst,   // reset external buffer address to page start 
Andrey Filippov's avatar
Andrey Filippov committed
126
    // extras
127 128
    input                        cmda_en, // tristate command and address lines // not likely to be used
    input                        ddr_rst, // generate reset to DDR3 memory (active high)
129 130
    input                        dci_rst, // active high - reset DCI circuitry
    input                        dly_rst, // active high - delay calibration circuitry
131
    input                        ddr_cke, // DDR clock enable , XOR-ed with command bit
Andrey Filippov's avatar
Andrey Filippov committed
132 133
    input                        inv_clk_div,
    input                 [7:0]  dqs_pattern, // 8'h55
134 135 136 137 138
    input                 [7:0]  dqm_pattern,  // 8'h00
    input                 [ 3:0] dq_tri_on_pattern,  // DQ tri-state control word, first when enabling output
    input                 [ 3:0] dq_tri_off_pattern, // DQ tri-state control word, first after disabling output
    input                 [ 3:0] dqs_tri_on_pattern, // DQS tri-state control word, first when enabling output
    input                 [ 3:0] dqs_tri_off_pattern // DQS tri-state control word, first after disabling output
Andrey Filippov's avatar
Andrey Filippov committed
139 140 141 142 143
);

// Decoding phy_cmd[35:0] into individual fields;
    wire    [ADDRESS_NUMBER-1:0] phy_addr_in;  // also provides pause length when the command is NOP
    wire                  [ 2:0] phy_bank_in;
144
    wire                  [ 2:0] phy_rcw_pos; // positive lof=gic for RAS, CAS, WE (0 - NOP)
145
    wire                  [ 2:0] phy_rcw_in; // {ras,cas,we}
146
    
Andrey Filippov's avatar
Andrey Filippov committed
147
    wire                         phy_odt_in; // may be optimized?
148
    wire                         phy_cke_dis; // command bit 0: enable CKE, 1 - disable CKE 
Andrey Filippov's avatar
Andrey Filippov committed
149
    wire                         phy_cke_in; // may be optimized?
150 151 152 153 154 155 156
    wire                         phy_sel_in; // first/second half-cycle, oter will be nop (cke+odt applicable to both)
    wire                         phy_dq_en_in;
    wire                         phy_dqs_en_in;
    wire                           phy_dq_tri_in;   // tristate DQ  lines (internal timing sequencer for 0->1 and 1->0)
    wire                           phy_dqs_tri_in;  // tristate DQS lines (internal timing sequencer for 0->1 and 1->0)
    wire                         phy_dci_en_in;      // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
    wire                           phy_dci_in;      // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
157
    wire                         phy_dqs_toggle_en;  //enable toggle DQS according to the pattern
Andrey Filippov's avatar
Andrey Filippov committed
158 159
    wire                         phy_buf_wr;   // connect to extrenal buffer
    wire                         phy_buf_rd;   // connect to extrenal buffer
160
    wire                         phy_buf_rst;  // reset buffers to page start
161
    wire                         cmda_tri;
162 163 164 165 166 167 168 169 170 171 172
 
    wire                  [2:0]  phy_rcw_cur; // {ras,cas,we}
    wire                         phy_odt_cur;       //
    wire                         phy_cke_dis_cur;      // disable cke (0 - enable), also controlled by a command bit ddr_cke (XOR-ed)
    wire                         phy_sel_cur;       // first/second half-cycle, oter will be nop (cke+odt applicable to both)
    wire                         phy_dq_en_cur;     //phy_dq_tri_in,   // tristate DQ  lines (internal timing sequencer for 0->1 and 1->0)
    wire                         phy_dqs_en_cur;    //phy_dqs_tri_in,  // tristate DQS lines (internal timing sequencer for 0->1 and 1->0)
    wire                         phy_dqs_toggle_cur;//enable toggle DQS according to the pattern
    wire                         phy_dci_en_cur;    //phy_dci_in,      // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
    wire                         phy_buf_wr_cur;       // connect to external buffer (but only if not paused)
    wire                         phy_buf_rd_cur;        // connect to external buffer (but only if not paused)
173
    wire                         phy_buf_rst_cur;
Andrey Filippov's avatar
Andrey Filippov committed
174 175 176 177 178 179 180 181 182 183 184 185
    
    wire                         clk_div;

    reg                    [7:0] dly_data_r; // delay value (3 LSB - fine delay)
    reg                    [6:0] dly_addr_r; // select which delay to program
    reg                          ld_delay_r; // load delay data to selected iodelayl (clk_div synchronous)
    reg                          set_r;       // clk_div synchronous set all delays from previously loaded values

    wire  [2*ADDRESS_NUMBER-1:0] phy_addr;  // also provides pause length when the command is NOP
    wire                  [ 5:0] phy_bank;
    wire                  [ 5:0] phy_rcw; // {ras,cas,we}
    wire                   [1:0] phy_odt; // may be optimized?
186
    wire                   [1:0] phy_cke; // may be optphy_dqs_tri_inimized?
Andrey Filippov's avatar
Andrey Filippov committed
187 188 189 190 191 192 193 194 195
    wire                   [7:0] phy_dq_tri;   // tristate DQ  lines (internal timing sequencer for 0->1 and 1->0)
    wire                   [7:0] phy_dqs_tri;  // tristate DQS lines (internal timing sequencer for 0->1 and 1->0)
    wire                         phy_dci_dis_dq; 
    wire                         phy_dci_dis_dqs;
        
    reg                          dqs_tri_prev, dq_tri_prev;
    wire                         phy_ps_rdy;
    wire       [PHASE_WIDTH-1:0] phy_ps_out; 
    reg                          ps_rdy_r1,ps_rdy_r2;
196 197 198 199 200 201
    reg                          locked_mmcm_r1,locked_mmcm_r2;
    reg                          locked_pll_r1, locked_pll_r2;
    reg                          dly_ready_r1, dly_ready_r2;
    reg                          dci_ready_r1, dci_ready_r2;
    
    
Andrey Filippov's avatar
Andrey Filippov committed
202 203 204
    reg        [PHASE_WIDTH-1:0] ps_out_r1,ps_out_r2; 
    wire                  [63:0] phy_rdata; // data read from ddr3 iserdese2 at posedge clk_div
    reg                   [63:0] phy_rdata_r; // registered @ posedge mclk
205 206 207 208 209
    
    reg    [ADDRESS_NUMBER-1:0] phy_addr_prev;
    reg                  [ 2:0] phy_bank_prev;
    wire   [ADDRESS_NUMBER-1:0] phy_addr_calm;
    wire                 [ 2:0] phy_bank_calm;
210
    reg                  [ 9:0] extra_prev;
211
    
Andrey Filippov's avatar
Andrey Filippov committed
212 213 214
    assign {
        phy_addr_in,
        phy_bank_in,
215
        phy_rcw_pos,      // {ras,cas,we}
216
        phy_odt_in,      // 
217
        phy_cke_dis,     // disable cke (0 - enable), also controlled by a command bit ddr_cke (XOR-ed)
Andrey Filippov's avatar
Andrey Filippov committed
218
        phy_sel_in,      // fitst/second half-cycle, oter will be nop (cke+odt applicable to both)
219 220
        phy_dq_en_in, //phy_dq_tri_in,   // tristate DQ  lines (internal timing sequencer for 0->1 and 1->0)
        phy_dqs_en_in, //phy_dqs_tri_in,  // tristate DQS lines (internal timing sequencer for 0->1 and 1->0)
221
        phy_dqs_toggle_en,   //enable toggle DQS according to the pattern
222
        phy_dci_en_in, //phy_dci_in,      // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
223 224
        phy_buf_wr,   // connect to external buffer (but only if not paused)
        phy_buf_rd,    // connect to external buffer (but only if not paused)
225
        phy_cmd_add_pause, // add nop to current command
226
        phy_buf_rst // phy_spare      // Reserved for future use
227
    } =  phy_cmd_word;
228 229
    
    assign {
Andrey Filippov's avatar
Andrey Filippov committed
230
        phy_rcw_cur[2:0],  // all set to 0 
231 232 233 234 235 236 237 238 239 240
        phy_odt_cur,       // 9 8 ODT
        phy_cke_dis_cur,   // 8 7 disable cke (0 - enable), also controlled by a command bit ddr_cke (XOR-ed)
        phy_sel_cur,       // 7 6 first/second half-cycle, other will be nop (cke+odt applicable to both) - NOT USED?
        phy_dq_en_cur,     // 6 5 phy_dq_tri_in,   // tristate DQ  lines (internal timing sequencer for 0->1 and 1->0)
        phy_dqs_en_cur,    // 5 4 phy_dqs_tri_in,  // tristate DQS lines (internal timing sequencer for 0->1 and 1->0)
        phy_dqs_toggle_cur,// 4 3 enable toggle DQS according to the pattern
        phy_dci_en_cur,    // 3 2 phy_dci_in,      // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
        phy_buf_wr_cur,    // 2 1 connect to external buffer (but only if not paused)
        phy_buf_rd_cur,    // 1 0 connect to external buffer (but only if not paused)
        phy_buf_rst_cur    // 0
241 242 243 244 245 246 247 248 249 250 251
    } =  add_pause ? {3'b0, extra_prev} : // 3'b0 for rcw (nop)
    {
        phy_rcw_pos[2:0],      // {ras,cas,we}
        phy_odt_in,      // may be optimized?
        phy_cke_dis,     // disable cke (0 - enable), also controlled by a command bit ddr_cke (XOR-ed)
        phy_sel_in,      // first/second half-cycle, oter will be nop (cke+odt applicable to both)
        phy_dq_en_in, //phy_dq_tri_in,   // tristate DQ  lines (internal timing sequencer for 0->1 and 1->0)
        phy_dqs_en_in, //phy_dqs_tri_in,  // tristate DQS lines (internal timing sequencer for 0->1 and 1->0)
        phy_dqs_toggle_en,   //enable toggle DQS according to the pattern
        phy_dci_en_in, //phy_dci_in,      // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
        phy_buf_wr,   // connect to external buffer (but only if not paused)
252 253
        phy_buf_rd,    // connect to external buffer (but only if not paused)
        phy_buf_rst
254 255 256 257 258 259 260
    };
    assign phy_cke_in=     phy_cke_dis_cur ^ ddr_cke;
    assign phy_dq_tri_in= ~phy_dq_en_cur;
    assign phy_dqs_tri_in=~phy_dqs_en_cur;
    assign phy_dci_in=    ~phy_dci_en_cur;
    assign phy_rcw_in=    ~phy_rcw_cur;
    assign phy_cmd_nop=   (phy_rcw_pos==0) && !add_pause; // ignores inserted NOP
261
    assign sequence_done= phy_cmd_nop && phy_addr_in[CMD_DONE_BIT];
262
    assign pause_len=      phy_addr_in[CMD_DONE_BIT]? 0: phy_addr_in[CMD_PAUSE_BITS-1:0]; // protect from non-zero length with done bit
Andrey Filippov's avatar
Andrey Filippov committed
263
    
264 265 266 267
    assign phy_addr_calm= (phy_cmd_nop || add_pause) ? phy_addr_prev : phy_addr_in;
    assign phy_bank_calm= (phy_cmd_nop || add_pause) ? phy_bank_prev : phy_bank_in;
    assign buf_wr =   phy_buf_wr_cur;
    assign buf_rd =   phy_buf_rd_cur;
268
    assign buf_rst=   phy_buf_rst_cur;
Andrey Filippov's avatar
Andrey Filippov committed
269
    
270 271
    assign  phy_addr=   {phy_addr_calm,phy_addr_calm};       // also provides pause length when the command is NOP
    assign  phy_bank=   {phy_bank_calm,phy_bank_calm};
272 273 274
    assign  phy_rcw=    {phy_sel_cur?phy_rcw_in:3'h7, phy_sel_cur?3'h7:phy_rcw_in}; // {ras,cas,we}
    assign  phy_odt=    {phy_odt_cur,phy_odt_cur};
    assign  phy_cke=    {phy_cke_in,phy_cke_in};
Andrey Filippov's avatar
Andrey Filippov committed
275 276 277
    
    // tristate DQ  lines (internal timing sequencer for 0->1 and 1->0)
    assign  phy_dq_tri= (dq_tri_prev==phy_dq_tri_in)?{{8{phy_dq_tri_in}}}:
278
                          (dq_tri_prev?{dq_tri_on_pattern,dq_tri_on_pattern}:{dq_tri_off_pattern,dq_tri_off_pattern});
Andrey Filippov's avatar
Andrey Filippov committed
279 280
    // tristate DQS  lines (internal timing sequencer for 0->1 and 1->0)
    assign  phy_dqs_tri= (dqs_tri_prev==phy_dqs_tri_in)?{{8{phy_dqs_tri_in}}}:
281
                          (dqs_tri_prev?{dqs_tri_on_pattern,dqs_tri_on_pattern}:{dqs_tri_off_pattern,dqs_tri_off_pattern});
Andrey Filippov's avatar
Andrey Filippov committed
282
    assign  phy_dci_dis_dq =   phy_dci_in;         // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
283
    assign  phy_dci_dis_dqs =  phy_dci_in || phy_odt_cur;  // In write leveling mode phy_dci_in = 0, phy_odt_cur=1 - use DCI on DQ only, no DQS
Andrey Filippov's avatar
Andrey Filippov committed
284 285 286 287
    
    assign  ps_rdy = ps_rdy_r2;
    assign  ps_out = ps_out_r2;
    
288 289 290 291 292
    assign  locked_mmcm = locked_mmcm_r2;
    assign  locked_pll = locked_pll_r2;
    assign  dly_ready = dly_ready_r2;
    assign  dci_ready = dci_ready_r2;
    
Andrey Filippov's avatar
Andrey Filippov committed
293 294
    assign buf_wdata[63:0] = phy_rdata_r[63:0];
    
295 296
    assign cmda_tri=!cmda_en;
    
Andrey Filippov's avatar
Andrey Filippov committed
297 298 299 300
    always @ (posedge mclk) begin
        dqs_tri_prev <= phy_dqs_tri_in;
        dq_tri_prev  <= phy_dq_tri_in;
    end 
301

Andrey Filippov's avatar
Andrey Filippov committed
302 303
    always @ (posedge mclk) begin
        if (mrst) begin
304 305
            phy_addr_prev <= 0;
            phy_bank_prev <= 0;
306
            extra_prev    <= 0;
307 308 309
        end else if (!phy_cmd_nop) begin
            phy_addr_prev <= phy_addr_in;
            phy_bank_prev <= phy_bank_in;
310
            extra_prev <=  {
311 312 313 314 315 316 317 318 319 320
                   phy_odt_in,       // 9 8 may be optimized?
                   phy_cke_dis,      // 8 7 disable cke (0 - enable), also controlled by a command bit ddr_cke (XOR-ed)
                   phy_sel_in,       // 7 6 first/second half-cycle, other will be nop (cke+odt applicable to both)
                   phy_dq_en_in,     // 6 5 phy_dq_tri_in,   // tristate DQ  lines (internal timing sequencer for 0->1 and 1->0)
                   phy_dqs_en_in,    // 5 4 phy_dqs_tri_in,  // tristate DQS lines (internal timing sequencer for 0->1 and 1->0)
                   phy_dqs_toggle_en,// 4 3 enable toggle DQS according to the pattern
                   phy_dci_en_in,    // 3 2 phy_dci_in,      // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
                   phy_buf_wr,       // 2 1 connect to external buffer (but only if not paused)
                   phy_buf_rd,       // 1 0 connect to external buffer (but only if not paused)
                   phy_buf_rst       // 0 connect to external buffer (but only if not paused)
321 322
            };
            
323 324 325
        end
            
    end
Andrey Filippov's avatar
Andrey Filippov committed
326
    
Andrey Filippov's avatar
Andrey Filippov committed
327 328 329 330 331 332
// cross clock boundary posedge mclk -> posedge clk_div (mclk is later than clk_div)
    reg rst_clk_div = 1;
    always @ (posedge clk_div) rst_clk_div <= mrst;

    always @ (posedge clk_div) begin
        if (rst_clk_div) begin
Andrey Filippov's avatar
Andrey Filippov committed
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
            dly_data_r <= 0;
            dly_addr_r <= 0;
            ld_delay_r <= 0;
            set_r      <= 0;
        end else begin
            dly_data_r <= dly_data;
            dly_addr_r <= dly_addr;
            ld_delay_r <= ld_delay;
            set_r      <= set;
        end
    end
    
    
// cross clock boundary posedge posedge clk_div->negedge clk_div -> posedge mclk  (mclk is later than clk_div)    
    always @ (negedge clk_div) begin
        ps_rdy_r1 <=   phy_ps_rdy;
349 350 351 352 353 354 355
        ps_out_r1 <=   phy_ps_out;
        
        locked_mmcm_r1 <= phy_locked_mmcm;
        locked_pll_r1  <= phy_locked_pll;
        dly_ready_r1   <= phy_dly_ready;
        dci_ready_r1   <= phy_dci_ready;
        
Andrey Filippov's avatar
Andrey Filippov committed
356 357 358 359
    end
    always @ (posedge mclk) begin
        ps_rdy_r2 <=   ps_rdy_r1;
        ps_out_r2 <=   ps_out_r1; 
360 361 362 363 364

        locked_mmcm_r2 <= locked_mmcm_r1;
        locked_pll_r2  <= locked_pll_r1;
        dly_ready_r2   <= dly_ready_r1;
        dci_ready_r2   <= dci_ready_r1;
Andrey Filippov's avatar
Andrey Filippov committed
365 366 367 368 369 370 371 372 373
    end


    always @ (negedge mclk) begin
        phy_rdata_r[63:0] <= phy_rdata[63:0];
    end



374
    wire [7:0] dqs_data;
375 376
  assign dqs_data=phy_dqs_toggle_cur?dqs_pattern[7:0]:8'h0; // Has to be low to satisfy write levelling preamble

Andrey Filippov's avatar
Andrey Filippov committed
377 378
    phy_top #(
        .IOSTANDARD_DQ      ("SSTL15_T_DCI"),
379
        .IOSTANDARD_DM      ("SSTL15"),
Andrey Filippov's avatar
Andrey Filippov committed
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
        .IOSTANDARD_DQS     ("DIFF_SSTL15_T_DCI"),
        .IOSTANDARD_CMDA    ("SSTL15"),
        .IOSTANDARD_CLK     ("DIFF_SSTL15"),
        .SLEW_DQ          (SLEW_DQ),
        .SLEW_DQS         (SLEW_DQS),
        .SLEW_CMDA        (SLEW_CMDA),
        .SLEW_CLK         (SLEW_CLK),
        .IBUF_LOW_PWR     (IBUF_LOW_PWR),
        .IODELAY_GRP        ("IODELAY_MEMORY"),
        .REFCLK_FREQUENCY (REFCLK_FREQUENCY),
        .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE),
        .ADDRESS_NUMBER   (ADDRESS_NUMBER),
        .PHASE_WIDTH        (8),
        .BANDWIDTH        ("OPTIMIZED"),
        .CLKIN_PERIOD     (CLKIN_PERIOD),
        .CLKFBOUT_MULT    (CLKFBOUT_MULT),
        .DIVCLK_DIVIDE    (DIVCLK_DIVIDE),
397
        .CLKFBOUT_USE_FINE_PS (CLKFBOUT_USE_FINE_PS),
Andrey Filippov's avatar
Andrey Filippov committed
398
        .CLKFBOUT_PHASE   (CLKFBOUT_PHASE),
Andrey Filippov's avatar
Andrey Filippov committed
399
        .SDCLK_PHASE      (SDCLK_PHASE),
Andrey Filippov's avatar
Andrey Filippov committed
400 401 402 403 404 405 406 407
        .CLK_PHASE        (CLK_PHASE),
        .CLK_DIV_PHASE    (CLK_DIV_PHASE),
        .MCLK_PHASE       (MCLK_PHASE),
        .REF_JITTER1         (REF_JITTER1),
        .SS_EN            (SS_EN),
        .SS_MODE          (SS_MODE),
        .SS_MOD_PERIOD    (SS_MOD_PERIOD)
    ) phy_top_i (
Andrey Filippov's avatar
Andrey Filippov committed
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
        .ddr3_nrst       (SDRST),                          // output
        .ddr3_clk        (SDCLK),                          // output
        .ddr3_nclk       (SDNCLK),                         // output
        .ddr3_a          (SDA[ADDRESS_NUMBER-1:0]),        // output[14:0] 
        .ddr3_ba         (SDBA[2:0]),                      // output[2:0] 
        .ddr3_we         (SDWE),                           // output
        .ddr3_ras        (SDRAS),                          // output
        .ddr3_cas        (SDCAS),                          // output
        .ddr3_cke        (SDCKE),                          // output
        .ddr3_odt        (SDODT),                          // output
        .dq              (SDD[15:0]),                      // inout[15:0] 
        .dml             (SDDML),                          // inout
        .dqsl            (DQSL),                           // inout
        .ndqsl           (NDQSL),                          // inout
        .dmu             (SDDMU),                          // inout
        .dqsu            (DQSU),                           // inout
        .ndqsu           (NDQSU),                          // inout
        .clk_in          (clk_in),                         // input
        .clk             (),                               // output
        .clk_div         (clk_div),                        // output
        .mclk            (mclk),                           // output
        .mrst            (mrst),                           // input
430
        .ref_clk         (ref_clk),                        // input
Andrey Filippov's avatar
Andrey Filippov committed
431
        .idelay_ctrl_reset (idelay_ctrl_reset),            // output
432

Andrey Filippov's avatar
Andrey Filippov committed
433 434 435 436
        .rst_in          (rst_in),                         // input
        .ddr_rst         (ddr_rst),                        // input
        .dci_rst         (dci_rst),                        // input
        .dly_rst         (dly_rst),                        // input
Andrey Filippov's avatar
Andrey Filippov committed
437
        .in_a            (phy_addr[2*ADDRESS_NUMBER-1:0]), // input[29:0] 
Andrey Filippov's avatar
Andrey Filippov committed
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
        .in_ba           (phy_bank[5:0]),                  // input[5:0] 
        .in_we           ({phy_rcw[3],phy_rcw[0]}),        // input[1:0] 
        .in_ras          ({phy_rcw[5],phy_rcw[2]}),        // input[1:0] 
        .in_cas          ({phy_rcw[4],phy_rcw[1]}),        // input[1:0] 
        .in_cke          (phy_cke),                        // input[1:0] 
        .in_odt          (phy_odt),                        // input[1:0] 
        .in_tri          (cmda_tri),                       // input
        .din             (buf_rdata[63:0]),                // input[63:0] 
        .din_dm          (dqm_pattern[7:0]),               // input[7:0] 
        .tin_dq          (phy_dq_tri[7:0]),                // input[7:0] 
        .din_dqs         (dqs_data),                       // input[7:0] 
        .tin_dqs         (phy_dqs_tri[7:0]),               // input[7:0] 
        .dout            (phy_rdata[63:0]),                // output[63:0] @posedge clk_div
        .inv_clk_div     (inv_clk_div),                    // input
        .dci_disable_dqs (phy_dci_dis_dqs),                // input
        .dci_disable_dq  (phy_dci_dis_dq),                 // input
        .dly_data        (dly_data_r),                     // input[7:0] 
        .dly_addr        (dly_addr_r),                     // input[6:0] 
        .ld_delay        (ld_delay_r),                     // input
        .set             (set_r),                          // input
        .locked_mmcm     (phy_locked_mmcm),                // output
        .locked_pll      (phy_locked_pll),                 // output
        .dly_ready       (phy_dly_ready),                  // output
        .dci_ready       (phy_dci_ready),                  // output
        .tmp_debug       (tmp_debug[7:0]),                 // output[7:0]
        .ps_rdy          (phy_ps_rdy),                     // output
        .ps_out          (phy_ps_out)                      // output[7:0] 
Andrey Filippov's avatar
Andrey Filippov committed
465 466 467 468
    );

endmodule