ddrc_sequencer.v 20.8 KB
Newer Older
Andrey Filippov's avatar
Andrey Filippov committed
1
/*******************************************************************************
2
 * Module: ddrc_sequencer
Andrey Filippov's avatar
Andrey Filippov committed
3 4
 * Date:2014-05-16  
 * Author: Andrey Filippov
5
 * Description: ddr3 sequnecer
Andrey Filippov's avatar
Andrey Filippov committed
6 7
 *
 * Copyright (c) 2014 Elphel, Inc.
8
 * ddrc_sequencer.v is free software; you can redistribute it and/or modify
Andrey Filippov's avatar
Andrey Filippov committed
9 10 11 12
 * 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.
 *
13
 *  ddrc_sequencer.v is distributed in the hope that it will be useful,
Andrey Filippov's avatar
Andrey Filippov committed
14 15 16 17 18 19 20 21 22
 * 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/> .
 *******************************************************************************/
`timescale 1ns/1ps

23
module  ddrc_sequencer   #(
Andrey Filippov's avatar
Andrey Filippov committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37
    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 CLKFBOUT_MULT_REF =   9, // Fvco=Fclkin*CLKFBOUT_MULT_F/DIVCLK_DIVIDE, Fout=Fvco/CLKOUT#_DIVIDE
    parameter CLKFBOUT_DIV_REF =    3, // To get 300MHz for the reference clock
    parameter DIVCLK_DIVIDE=        1,
    parameter CLKFBOUT_PHASE =      0.000,
Andrey Filippov's avatar
Andrey Filippov committed
38
    parameter SDCLK_PHASE =         0.000,
Andrey Filippov's avatar
Andrey Filippov committed
39 40 41 42 43 44 45
    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",
    parameter SS_MOD_PERIOD =       10000,
46 47
    parameter CMD_PAUSE_BITS=       10,
    parameter CMD_DONE_BIT=         10
Andrey Filippov's avatar
Andrey Filippov committed
48 49
)(
    // DDR3 interface
50
    output                       SDRST, // DDR3 reset (active low)
Andrey Filippov's avatar
Andrey Filippov committed
51 52 53 54 55 56 57 58 59 60
    output                       SDCLK, // DDR3 clock differential output, positive
    output                       SDNCLK,// DDR3 clock differential output, negative
    output  [ADDRESS_NUMBER-1:0] SDA,   // output address ports (14:0) for 4Gb device
    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

61
    inout                 [15:0] SDD,   // DQ  I/O pads
62
    output                       SDDML, // LDM  I/O pad (actually only output)
63 64
    inout                        DQSL,  // LDQS I/O pad
    inout                        NDQSL, // ~LDQS I/O pad
65
    output                       SDDMU, // UDM  I/O pad (actually only output)
66 67
    inout                        DQSU,  // UDQS I/O pad
    inout                        NDQSU, // ~UDQS I/O pad
Andrey Filippov's avatar
Andrey Filippov committed
68 69 70 71
// clocks, reset
    input                        clk_in,
    input                        rst_in,
    output                       mclk,     // global clock, half DDR3 clock, synchronizes all I/O thorough the command port
72 73
// command port 0 (filled by software - 32w->32r) - used for mode set, refresh, write levelling, ...
    input                        cmd0_clk,
Andrey Filippov's avatar
Andrey Filippov committed
74 75 76
    input                        cmd0_we,
    input                [9:0]   cmd0_addr,
    input               [31:0]   cmd0_data,
77 78
// automatic command port1 , filled by the PL, 32w 32r, used for actual page R/W
    input                        cmd1_clk,
Andrey Filippov's avatar
Andrey Filippov committed
79 80
    input                        cmd1_we,
    input                [9:0]   cmd1_addr,
81
    input               [31:0]   cmd1_data,
Andrey Filippov's avatar
Andrey Filippov committed
82
// Controller run interface, posedge mclk
83
    input               [10:0]   run_addr, // controller sequencer start address (0..11'h3ff - cmd0, 11'h400..11'h7ff - cmd1)
Andrey Filippov's avatar
Andrey Filippov committed
84
    input                [3:0]   run_chn,  // data channel to use
85
    input                        run_seq,  // start controller sequence (will and with !ddr_rst for stable mclk)
86 87
    output                       run_done, // controller sequence finished
    output                       run_busy, // controller sequence in progress  
Andrey Filippov's avatar
Andrey Filippov committed
88 89 90 91 92
// 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
93 94 95 96 97 98 99 100 101 102 103
//    output                       locked,
    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
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
    output                       ps_rdy,
    output     [PHASE_WIDTH-1:0] ps_out, 
// read port 0
    input                        port0_clk,
    input                        port0_re,
    input                        port0_regen, 
    input                [1:0]   port0_page,
    input                [1:0]   port0_int_page,
    input                [7:0]   port0_addr,
    output              [31:0]   port0_data,
// write port 1
    input                        port1_clk,
    input                        port1_we,
    input                [1:0]   port1_page,
    input                [1:0]   port1_int_page,
    input                [7:0]   port1_addr,
    input               [31:0]   port1_data,
    // extras
122 123
    input                        cmda_en, // enable (!tristate) command and address lines // not likely to be used
    input                        ddr_rst, // generate reset to DDR3 memory (active high)
124 125
    input                        dci_rst,  // active high - reset DCI circuitry
    input                        dly_rst,  // active high - delay calibration circuitry
126
    input                        ddr_cke, // DDR clock enable , XOR-ed with command bit
Andrey Filippov's avatar
Andrey Filippov committed
127 128
    input                        inv_clk_div,
    input                 [7:0]  dqs_pattern, // 8'h55
129 130 131 132 133 134
    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
    input                 [ 3:0] wbuf_delay
Andrey Filippov's avatar
Andrey Filippov committed
135 136 137
);
    localparam ADDRESS_NUMBER = 15;
    
138 139 140 141 142 143 144 145 146 147 148 149
    
//    wire                 [35:0]  phy_cmd; // input[35:0] 
    wire                 [31:0]  phy_cmd_word;  // selected output from eithe cmd0 buffer or cmd1 buffer 
    wire                 [31:0]  phy_cmd0_word; // cmd0 buffer output
    wire                 [31:0]  phy_cmd1_word; // cmd1 buffer output
    reg                  [ 8:0]  buf_raddr;
    reg                  [ 8:0]  buf_waddr_negedge;
    reg                          buf_wr_negedge; 
    wire                 [63:0]  buf_wdata; // output[63:0]
    reg                  [63:0]  buf_wdata_negedge; // output[63:0]
    wire                 [63:0]  buf_rdata; // multiplexed input from one of the write channels buffer
    wire                 [63:0]  buf1_rdata;
150 151
    wire                         buf_wr; // delayed by specified number of clock cycles
    wire                         buf_wr_ndly; // before dealy
152 153 154 155 156 157 158 159 160
    wire                         buf_rd; // read next 64 bytes from the buffer, need one extra pre-read
    
    wire                         rst=rst_in;
  
//    wire                 [ 9:0]  next_cmd_addr;
    reg                  [ 9:0]  cmd_addr;      // command word adderss  
    reg                          cmd_sel;
    reg                  [ 2:0]  cmd_busy;      // bit 0 - immediately,
    wire                         phy_cmd_nop;   // decoded command (ras, cas, we) was NOP
161 162
    wire                         phy_cmd_add_pause; // decoded from the command word - add one pause command after the current one
    reg                          add_pause; // previos command had phy_cmd_add_pause set
163 164 165 166 167 168 169 170 171 172 173 174
    wire                         sequence_done;
    wire   [CMD_PAUSE_BITS-1:0]  pause_len;
    reg                          cmd_fetch;     // previous cycle command was read from the command memory, current: command valid
    wire                         pause;         // do not register new data from the command memory
    reg    [CMD_PAUSE_BITS-1:0]  pause_cntr;
    
    reg                   [1:0]  buf_page;      // one of 4 pages in the channel buffer to use for R/W
    reg                  [15:0]  buf_sel_1hot; // 1 hot channel buffer select
    
    reg                   [3:0]  run_chn_d;
    reg                          run_seq_d; 
    
175 176 177 178 179 180 181 182 183 184 185 186
//    reg tmp_dbg7=0;
    wire [7:0] tmp_debug_a;
    /*
    always @ (posedge clk_in) begin
        tmp_dbg7 <= ~tmp_dbg7;
    end
    
    assign tmp_debug[7:0] = {tmp_dbg7,tmp_debug_a[6:0]};
    */
    assign tmp_debug[7:0] = tmp_debug_a[7:0];
 //   clk_in
    
187
    assign run_done=sequence_done;
188
    assign run_busy=cmd_busy[0]; //earliest
189
    assign  pause=cmd_fetch? (phy_cmd_add_pause || (phy_cmd_nop && (pause_len != 0))): (cmd_busy[2] && (pause_cntr[CMD_PAUSE_BITS-1:1]!=0));
190 191 192
/// debugging
    assign phy_cmd_word = cmd_sel?phy_cmd1_word:phy_cmd0_word; // TODO: hangs even with 0-s in phy_cmd
///    assign phy_cmd_word = phy_cmd_word?0:0;
193
     
194
    assign buf_rdata[63:0] = ({64{buf_sel_1hot[1]}} & buf1_rdata[63:0]); // ORed with other read channels terms   
195 196 197
    
    always @ (posedge mclk or posedge rst) begin
        if (rst)                cmd_busy <= 0;
198
//        else if (sequence_done) cmd_busy <= 0;
199 200

        else if (ddr_rst) cmd_busy <= 0; // *************** reset sequencer with DDR reset
201
        else if (sequence_done &&  cmd_busy[2]) cmd_busy <= 0;
202
        else cmd_busy <= {cmd_busy[1:0],run_seq | cmd_busy[0]}; 
203 204 205 206
        // Pause counter
        if (rst)                           pause_cntr <= 0;
        else if (!cmd_busy[1])             pause_cntr <= 0; // not needed?
        else if (cmd_fetch && phy_cmd_nop) pause_cntr <= pause_len;
207
        else if (pause_cntr!=0)            pause_cntr <= pause_cntr-1; //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 10-bit target.
208 209 210
        // Fetch - command data valid
        if (rst) cmd_fetch <= 0;
        else     cmd_fetch <= cmd_busy[0] && !pause;
211 212 213 214

        if (rst) add_pause <= 0;
        else     add_pause <= cmd_fetch && phy_cmd_add_pause;
         
215
        // Command read address
216 217
        if (rst)                        cmd_addr <= 0;
        else  if (run_seq)              cmd_addr <= run_addr[9:0];
218
        else if (cmd_busy[0] && !pause) cmd_addr <= cmd_addr + 1; //SuppressThisWarning ISExst Result of 11-bit expression is truncated to fit in 10-bit target.
219 220 221
        // command bank select (0 - "manual" (software programmed sequences), 1 - "auto" (normal block r/w)
        if (rst)            cmd_sel <= 0;
        else  if (run_seq)  cmd_sel <= run_addr[10];
222
   
223 224 225 226
        if (rst)            buf_page <= 0;
        else  if (run_seq)  case (run_chn)
            4'h0:    buf_page <= port0_int_page;
            4'h1:    buf_page <= port1_int_page;
227
            // Add other channels later
228 229
            default: buf_page <= 2'bxx; 
        endcase
230
       
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
        if (rst)            buf_sel_1hot <= 0;
        else buf_sel_1hot <= {
            (run_chn_d==4'hf)?1'b1:1'b0,
            (run_chn_d==4'he)?1'b1:1'b0,
            (run_chn_d==4'hd)?1'b1:1'b0,
            (run_chn_d==4'hc)?1'b1:1'b0,
            (run_chn_d==4'hb)?1'b1:1'b0,
            (run_chn_d==4'ha)?1'b1:1'b0,
            (run_chn_d==4'h9)?1'b1:1'b0,
            (run_chn_d==4'h8)?1'b1:1'b0,
            (run_chn_d==4'h7)?1'b1:1'b0,
            (run_chn_d==4'h6)?1'b1:1'b0,
            (run_chn_d==4'h5)?1'b1:1'b0,
            (run_chn_d==4'h4)?1'b1:1'b0,
            (run_chn_d==4'h3)?1'b1:1'b0,
            (run_chn_d==4'h2)?1'b1:1'b0,
            (run_chn_d==4'h1)?1'b1:1'b0,
            (run_chn_d==4'h0)?1'b1:1'b0 };
        if (rst)                   buf_raddr <= 9'h0;
        else if (run_seq_d)        buf_raddr <= {buf_page,7'h0};
251
        else if (buf_wr || buf_rd) buf_raddr <= buf_raddr +1; // Separate read/write address? read address re-registered @ negedge //SuppressThisWarning ISExst Result of 10-bit expression is truncated to fit in 9-bit target.
252

253 254
        if (rst)          run_chn_d <= 0;
        else if (run_seq) run_chn_d <= run_chn;
255 256 257
        if (rst) run_seq_d <= 0;
        else run_seq_d <= run_seq;
        
258 259 260 261 262 263 264 265 266
    end
    // re-register buffer write address to match DDR3 data
    always @ (negedge mclk) begin
        buf_waddr_negedge <= buf_raddr;
        buf_wr_negedge <= buf_wr;
        buf_wdata_negedge <= buf_wdata;
    end
// Command sequence memories:
// Command sequence memory 0 ("manual"):
267 268
    wire ren0=!cmd_sel && cmd_busy[0] && !pause; // cmd_busy - multibit
    wire ren1= cmd_sel && cmd_busy[0] && !pause;
269
    ram_1kx32_1kx32 #(
270
        .REGISTERS(1) // (0) // register output
271 272
    ) cmd0_buf_i (
        .rclk     (mclk), // input
273 274 275 276 277
        .raddr    (cmd_addr), // input[9:0]
///        .ren      (!cmd_sel && cmd_busy && !pause), // input
///        .regen    (!cmd_sel && cmd_busy && !pause), // input
        .ren      (ren0), // input TODO: verify cmd_busy[0] is correct (was cmd_busy )
        .regen    (ren0), // input
278 279 280 281 282 283 284 285 286 287
        .data_out (phy_cmd0_word), // output[31:0] 
        .wclk     (cmd0_clk), // input
        .waddr    (cmd0_addr), // input[9:0] 
        .we       (cmd0_we), // input
        .web      (4'hf), // input[3:0] 
        .data_in  (cmd0_data) // input[31:0] 
    );

// Command sequence memory 0 ("manual"):
    ram_1kx32_1kx32 #(
288
        .REGISTERS(1) // (0) // register output
289 290
    ) cmd1_buf_i (
        .rclk     (mclk), // input
291 292 293 294 295
        .raddr    (cmd_addr), // input[9:0]
///        .ren      ( cmd_sel && cmd_busy && !pause), // input
///        .regen    ( cmd_sel && cmd_busy && !pause), // input
        .ren      ( ren1), // input
        .regen    ( ren1), // input
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
        .data_out (phy_cmd1_word), // output[31:0] 
        .wclk     (cmd1_clk), // input
        .waddr    (cmd1_addr), // input[9:0] 
        .we       (cmd1_we), // input
        .web      (4'hf), // input[3:0] 
        .data_in  (cmd1_data) // input[31:0] 
    );
// Port memory buffer (4 pages each, R/W fixed, port 0 - AXI read from DDR, port 1 - AXI write to DDR
// Port 0 (read DDR to AXI) buffer
    ram_512x64w_1kx32r #(
        .REGISTERS(1)
    ) port0_buf_i (
        .rclk     (port0_clk), // input
        .raddr    ({port0_page,port0_addr}), // input[9:0] 
        .ren      (port0_re), // input
        .regen    (port0_regen), // input
        .data_out (port0_data), // output[31:0] 
        .wclk     (!mclk), // input
        .waddr    (buf_waddr_negedge), // input[8:0] 
        .we       (buf_sel_1hot[0] && buf_wr_negedge), // input
        .web      (8'hff), // input[7:0] 
        .data_in  (buf_wdata_negedge) // input[63:0] 
    );
    
// Port 1 (write DDR from AXI) buffer
    ram_1kx32w_512x64r #(
        .REGISTERS(1)
    ) port1_buf_i (
        .rclk(mclk), // input
        .raddr(buf_raddr), // input[8:0] 
        .ren(buf_sel_1hot[1] && buf_rd), // input
        .regen(buf_sel_1hot[1] && buf_rd), // input
        .data_out(buf1_rdata), // output[63:0] 
        .wclk(port1_clk), // input
        .waddr({port1_page,port1_addr}), // input[9:0] 
        .we(port1_we), // input
        .web(4'hf), // input[3:0] 
        .data_in(port1_data) // input[31:0] 
    );
    
Andrey Filippov's avatar
Andrey Filippov committed
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
    
    
    phy_cmd #(
        .ADDRESS_NUMBER        (ADDRESS_NUMBER),
        .PHASE_WIDTH           (PHASE_WIDTH),
        .SLEW_DQ               (SLEW_DQ),
        .SLEW_DQS              (SLEW_DQS),
        .SLEW_CMDA             (SLEW_CMDA),
        .SLEW_CLK              (SLEW_CLK),
        .IBUF_LOW_PWR          (IBUF_LOW_PWR),
        .REFCLK_FREQUENCY      (REFCLK_FREQUENCY),
        .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
        .CLKIN_PERIOD          (CLKIN_PERIOD),
        .CLKFBOUT_MULT         (CLKFBOUT_MULT),
        .CLKFBOUT_MULT_REF     (CLKFBOUT_MULT_REF),
        .CLKFBOUT_DIV_REF      (CLKFBOUT_DIV_REF),
        .DIVCLK_DIVIDE         (DIVCLK_DIVIDE),
        .CLKFBOUT_PHASE        (CLKFBOUT_PHASE),
354 355
        .SDCLK_PHASE           (SDCLK_PHASE),/// debugging
        
Andrey Filippov's avatar
Andrey Filippov committed
356 357 358 359 360 361
        .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),
362 363 364 365
        .SS_MOD_PERIOD         (SS_MOD_PERIOD),
        .CMD_PAUSE_BITS        (CMD_PAUSE_BITS), // numer of (address) bits to encode pause
        .CMD_DONE_BIT          (CMD_DONE_BIT)    // bit number (address) to signal sequence done
        
Andrey Filippov's avatar
Andrey Filippov committed
366
    ) phy_cmd_i (
Andrey Filippov's avatar
Andrey Filippov committed
367
        .SDRST               (SDRST), // output
Andrey Filippov's avatar
Andrey Filippov committed
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
        .SDCLK               (SDCLK), // output
        .SDNCLK              (SDNCLK), // output
        .SDA                 (SDA[ADDRESS_NUMBER-1:0]), // output[14:0] 
        .SDBA                (SDBA[2:0]), // output[2:0] 
        .SDWE                (SDWE), // output
        .SDRAS               (SDRAS), // output
        .SDCAS               (SDCAS), // output
        .SDCKE               (SDCKE), // output
        .SDODT               (SDODT), // output
        .SDD                 (SDD[15:0]), // inout[15:0] 
        .SDDML               (SDDML), // inout
        .DQSL                (DQSL), // inout
        .NDQSL               (NDQSL), // inout
        .SDDMU               (SDDMU), // inout
        .DQSU                (DQSU), // inout
        .NDQSU               (NDQSU), // inout
        .clk_in              (clk_in), // input
        .rst_in              (rst_in), // input
        .mclk                (mclk), // output
        .dly_data            (dly_data[7:0]), // input[7:0] 
        .dly_addr            (dly_addr[6:0]), // input[6:0] 
        .ld_delay            (ld_delay), // input
        .set                 (set), // input
391 392 393 394 395 396 397 398 399 400 401 402 403
//        .locked              (locked), // output
        .locked_mmcm         (locked_mmcm), // output
        .locked_pll          (locked_pll), // output
        .dly_ready           (dly_ready), // output
        .dci_ready           (dci_ready), // output
        
        .phy_locked_mmcm     (phy_locked_mmcm), // output
        .phy_locked_pll      (phy_locked_pll), // output
        .phy_dly_ready       (phy_dly_ready), // output
        .phy_dci_ready       (phy_dci_ready), // output
        
        .tmp_debug           (tmp_debug_a[7:0]),
        
Andrey Filippov's avatar
Andrey Filippov committed
404
        .ps_rdy              (ps_rdy), // output
405 406
        .ps_out              (ps_out[7:0]), // output[7:0]
        .phy_cmd_word        (phy_cmd_word[31:0]), // input[31:0]
407
        .phy_cmd_nop         (phy_cmd_nop), // output
408 409
        .phy_cmd_add_pause   (phy_cmd_add_pause), // one pause cycle (for 8-bursts)
        .add_pause           (add_pause),
410 411
        .pause_len           (pause_len),     // output  [CMD_PAUSE_BITS-1:0]
        .sequence_done       (sequence_done), // output
Andrey Filippov's avatar
Andrey Filippov committed
412 413
        .buf_wdata           (buf_wdata[63:0]), // output[63:0] 
        .buf_rdata           (buf_rdata[63:0]), // input[63:0] 
414
        .buf_wr              (buf_wr_ndly), // output
Andrey Filippov's avatar
Andrey Filippov committed
415
        .buf_rd              (buf_rd), // output
416
        .cmda_en             (cmda_en), // input
417
        .ddr_rst             (ddr_rst), // input
418 419
        .dci_rst             (dci_rst), // input
        .dly_rst             (dly_rst), // input
420
        .ddr_cke             (ddr_cke), // input
Andrey Filippov's avatar
Andrey Filippov committed
421 422
        .inv_clk_div         (inv_clk_div), // input
        .dqs_pattern         (dqs_pattern), // input[7:0] 
423 424 425 426 427 428 429 430 431 432 433 434 435
        .dqm_pattern         (dqm_pattern), // input[7:0]
        .dq_tri_on_pattern   (dq_tri_on_pattern[3:0]),  // input[3:0] 
        .dq_tri_off_pattern  (dq_tri_off_pattern[3:0]), // input[3:0] 
        .dqs_tri_on_pattern  (dqs_tri_on_pattern[3:0]), // input[3:0] 
        .dqs_tri_off_pattern (dqs_tri_off_pattern[3:0]) // input[3:0] 
    );
    // delay buf_wr by 1-16 cycles to compensate for DDR and HDL code latency (~7 cycles?)
    dly01_16 buf_wr_dly_i (
        .clk(mclk), // input
        .rst(1'b0), // input
        .dly(wbuf_delay[3:0]), // input[3:0] 
        .din(buf_wr_ndly), // input
        .dout(buf_wr) // output reg 
Andrey Filippov's avatar
Andrey Filippov committed
436 437 438 439 440 441
    );



endmodule