/*******************************************************************************
* Module: mcontr_sequencer
* Date:2014-05-16
* Author: Andrey Filippov
* Description: ddr3 sequnecer
*
* Copyright (c) 2014 Elphel, Inc.
* mcontr_sequencer.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.
*
* mcontr_sequencer.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
module mcontr_sequencer #(
//command interface parameters
//0x1080..10ff - 8- bit data - to set various delay values
parameter DLY_LD = 'h080, // address to generate delay load
parameter DLY_LD_MASK = 'h380, // address mask to generate delay load
// 0x1080..109f - set delay for SDD0-SDD7
// 0x10a0..10bf - set delay for SDD8-SDD15
// 0x10c0..10df - set delay for SD_CMDA
// 0x10e0 - set delay for MMCM
//0x1000..103f - 0- bit data (set/reset)
parameter MCONTR_PHY_0BIT_ADDR = 'h020, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_0BIT_ADDR_MASK = 'h3f0, // address mask to generate sequencer channel/run
// 0x1024..1025 - CMDA_EN // 0 bits - enable/disable command/address outputs
// 0x1026..1027 - SDRST_ACT // 0 bits - enable/disable active-low reset signal to DDR3 memory
// 0x1028..1029 - CKE_EN // 0 bits - enable/disable CKE signal to memory
// 0x102a..102b - DCI_RST // 0 bits - enable/disable CKE signal to memory
// 0x102c..102d - DLY_RST // 0 bits - enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_SET = 'h0, // set pre-programmed delays
parameter MCONTR_PHY_0BIT_CMDA_EN = 'h4, // enable/disable command/address outputs
parameter MCONTR_PHY_0BIT_SDRST_ACT = 'h6, // enable/disable active-low reset signal to DDR3 memory
parameter MCONTR_PHY_0BIT_CKE_EN = 'h8, // enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DCI_RST = 'ha, // enable/disable CKE signal to memory
parameter MCONTR_PHY_0BIT_DLY_RST = 'hc, // enable/disable CKE signal to memory
parameter MCONTR_PHY_STATUS_REG_ADDR= 'h0, // status register address to use for memory controller phy
//0x1040..107f - 16-bit data
// 0x1040..104f - RUN_CHN // address to set sequncer channel and run (4 LSB-s - channel) - bits?
// parameter RUN_CHN_REL = 'h040, // address to set sequnecer channel and run (4 LSB-s - channel)
// parameter RUN_CHN_REL_MASK = 'h3f0, // address mask to generate sequencer channel/run
// 0x1050..1057: MCONTR_PHY16
parameter MCONTR_PHY_16BIT_ADDR = 'h050, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter MCONTR_PHY_16BIT_ADDR_MASK = 'h3f8, // address mask to generate sequencer channel/run
parameter MCONTR_PHY_16BIT_PATTERNS = 'h0, // set DQM and DQS patterns (16'h0055)
parameter MCONTR_PHY_16BIT_PATTERNS_TRI = 'h1, // 16-bit address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
parameter MCONTR_PHY_16BIT_WBUF_DELAY = 'h2, // 4? bits - extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
parameter MCONTR_PHY_16BIT_EXTRA = 'h3, // ? bits - set extra parameters (currently just inv_clk_div)
parameter MCONTR_PHY_STATUS_CNTRL = 'h4, // write to status control (8-bit)
parameter DFLT_DQS_PATTERN= 8'h55,
parameter DFLT_DQM_PATTERN= 8'h00, // 8'h00
parameter DFLT_DQ_TRI_ON_PATTERN= 4'h7, // DQ tri-state control word, first when enabling output
parameter DFLT_DQ_TRI_OFF_PATTERN= 4'he, // DQ tri-state control word, first after disabling output
parameter DFLT_DQS_TRI_ON_PATTERN= 4'h3, // DQS tri-state control word, first when enabling output
parameter DFLT_DQS_TRI_OFF_PATTERN=4'hc,// DQS tri-state control word, first after disabling output
parameter DFLT_WBUF_DELAY= 4'h6, // write levelling - 7!
parameter DFLT_INV_CLK_DIV= 1'b0,
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, 60032r) - used for mode set, refresh, write levelling, ...
input cmd0_clk,
input cmd0_we,
input [9:0] cmd0_addr,
input [31:0] cmd0_data,
// automatic command port1 , filled by the PL, 32w 32r, used for actual page R/W
input cmd1_clk,
input cmd1_we,
input [9:0] cmd1_addr,
input [31:0] cmd1_data,
// Controller run interface, posedge mclk
input [10:0] run_addr, // controller sequencer start address (0..11'h3ff - cmd0, 11'h400..11'h7ff - cmd1)
input [3:0] run_chn, // data channel to use
input run_seq, // start controller sequence (will and with !ddr_rst for stable mclk)
output run_done, // controller sequence finished
output run_busy, // controller sequence in progress
output mcontr_reset, // == ddr_reset that also resets sequencer
// programming interface
input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
input cmd_stb, // strobe (with first byte) for the command a/d
output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
output status_rq, // input request to send status downstream
input status_start, // Acknowledge of the first status packet byte (address)
// Interface to write-to-memory buffers (up to 16)
// There will be =1 cycle external latency in address/re and 1 cycle latency in read data (should match sequence programs)
// Address data is sync to posedge mclk
output ext_buf_rd,
output ext_buf_rpage_nxt, // increment external buffer read address to next page start
// output [6:0] ext_buf_raddr, // valid with ext_buf_rd, 2 page MSB to be generated externally
output [3:0] ext_buf_rchn, // ==run_chn_d valid 1 cycle ahead opf ext_buf_rd!, maybe not needed - will be generated externally
input [63:0] ext_buf_rdata, // Latency of ram_1kx32w_512x64r plus 2
// Interface to memory read channels (up to 16)
// Address/data sync to negedge mclk!, any latency OK - just generate DONE appropriately (through the sequencer with delay?
// folowing a sync to negedge!
output ext_buf_wr,
output ext_buf_wpage_nxt, // increment external buffer write address to next page start
// output [6:0] ext_buf_waddr, // valid with ext_buf_wr
output [3:0] ext_buf_wchn, // ==run_chn_d valid 1 cycle ahead of ext_buf_wr!, maybe not needed - will be generated externally
output [63:0] ext_buf_wdata, // valid with ext_buf_wr
// temporary debug data
output [11:0] tmp_debug
);
localparam ADDRESS_NUMBER = 15;
wire [7:0] dly_data;
wire [6:0] dly_addr;
wire ld_delay;
wire set;
wire [3:0] phy_0bit_addr;
wire phy_0bit_we;
reg cmda_en; // enable (!tristate) command and address lines // not likely to be used
reg ddr_rst=1; // generate reset to DDR3 memory (active high)
reg dci_rst; // active high - reset DCI circuitry
reg dly_rst; // active high - delay calibration circuitry
reg ddr_cke; // DDR clock enable , XOR-ed with command bit
reg [7:0] dqs_pattern=DFLT_DQS_PATTERN; // 8'h55
reg [7:0] dqm_pattern=DFLT_DQM_PATTERN; // 8'h00
reg [ 3:0] dq_tri_on_pattern=DFLT_DQ_TRI_ON_PATTERN; // DQ tri-state control word, first when enabling output
reg [ 3:0] dq_tri_off_pattern=DFLT_DQ_TRI_OFF_PATTERN; // DQ tri-state control word, first after disabling output
reg [ 3:0] dqs_tri_on_pattern=DFLT_DQS_TRI_ON_PATTERN; // DQS tri-state control word, first when enabling output
reg [ 3:0] dqs_tri_off_pattern=DFLT_DQS_TRI_OFF_PATTERN;// DQS tri-state control word, first after disabling output
reg [ 3:0] wbuf_delay=DFLT_WBUF_DELAY;
wire [2:0] phy_16bit_addr;
wire [15:0] phy_16bit_data;
wire phy_16bit_we;
reg inv_clk_div=0;
// Status data:
wire locked_mmcm;
wire locked_pll;
wire dly_ready;
wire dci_ready;
// wire [PHASE_WIDTH-1:0] ps_out;
wire [7:0] ps_out;
wire ps_rdy;
wire locked;
wire [14:0] status_data;
// temporary, debug
wire phy_locked_mmcm; // before clock crossing
wire phy_locked_pll; // before clock crossing
wire phy_dly_ready; // before clock crossing
wire phy_dci_ready; // before clock crossing
// 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
wire buf_raddr_reset;
// reg [ 6:0] buf_raddr;
reg buf_waddr_reset_negedge;
// reg [ 6: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;
wire buf_wr; // delayed by specified number of clock cycles
wire buf_wr_ndly; // before dealy
wire buf_rd; // read next 64 bits from the buffer, need one extra pre-read
wire buf_rst; // reset buffer address to
wire buf_rst_d; //buf_rst delayed to match buf_wr
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
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
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
wire [3:0] run_chn_w_d; // run chn delayed to match buf_wr delay
reg [3:0] run_chn_d;
reg [3:0] run_chn_w_d_negedge;
// reg run_seq_d;
wire [7:0] tmp_debug_a;
assign tmp_debug[11:0] =
{phy_locked_mmcm,
phy_locked_pll,
phy_dly_ready,
phy_dci_ready,
tmp_debug_a[7:0]};
assign mcontr_reset=ddr_rst; // to reset controller
assign run_done=sequence_done;
assign run_busy=cmd_busy[0]; //earliest
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));
/// 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;
// assign buf_rdata[63:0] = ({64{buf_sel_1hot[1]}} & buf1_rdata[63:0]); // ORed with other read channels terms
// External buffers buffer related signals
assign buf_raddr_reset= buf_rst; // run_seq_d;
assign ext_buf_rd= buf_rd;
assign ext_buf_rpage_nxt=buf_raddr_reset;
// assign ext_buf_raddr= buf_raddr;
assign ext_buf_rchn= run_chn_d;
assign buf_rdata[63:0] = ext_buf_rdata;
assign ext_buf_wr= buf_wr_negedge;
assign ext_buf_wpage_nxt=buf_waddr_reset_negedge;
// assign ext_buf_waddr= buf_waddr_negedge;
assign ext_buf_wchn= run_chn_w_d_negedge;
assign ext_buf_wdata= buf_wdata_negedge;
// generation of the control signals from byte-serial channel
// generate 8-bit delay data
cmd_deser #(
.ADDR (DLY_LD),
.ADDR_MASK (DLY_LD_MASK),
.NUM_CYCLES (3),
.ADDR_WIDTH (7),
.DATA_WIDTH (8)
) cmd_deser_dly_i (
.rst (rst), // input
.clk (mclk), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (dly_addr), // output[15:0]
.data (dly_data), // output[31:0]
.we( ld_delay) // output
);
// generate on/off dependent on lsb and 0-bit commands
cmd_deser #(
.ADDR (MCONTR_PHY_0BIT_ADDR),
.ADDR_MASK (MCONTR_PHY_0BIT_ADDR_MASK),
.NUM_CYCLES (2),
.ADDR_WIDTH (4),
.DATA_WIDTH (0)
) cmd_deser_0bit_i (
.rst (rst), // input
.clk (mclk), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (phy_0bit_addr), // output[15:0]
.data (), // output[31:0]
.we (phy_0bit_we) // output
);
assign set= phy_0bit_we && (phy_0bit_addr==MCONTR_PHY_0BIT_DLY_SET);
always @ (posedge mclk or posedge rst) begin
if (rst) cmda_en <= 0;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_CMDA_EN>>1))) cmda_en <= phy_0bit_addr[0];
if (rst) ddr_rst <= 1;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_SDRST_ACT>>1))) ddr_rst <= phy_0bit_addr[0];
if (rst) dci_rst <= 0;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_DCI_RST>>1))) dci_rst <= phy_0bit_addr[0];
if (rst) dly_rst <= 0;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_DLY_RST>>1))) dly_rst <= phy_0bit_addr[0];
if (rst) ddr_cke <= 0;
else if (phy_0bit_we && (phy_0bit_addr[3:1]==(MCONTR_PHY_0BIT_CKE_EN>>1))) ddr_cke <= phy_0bit_addr[0];
end
// generate 16-bit data commands (and set defaults to registers)
cmd_deser #(
.ADDR (MCONTR_PHY_16BIT_ADDR),
.ADDR_MASK (MCONTR_PHY_16BIT_ADDR_MASK),
.NUM_CYCLES (4),
.ADDR_WIDTH (3),
.DATA_WIDTH (16)
) cmd_deser_16bit_i (
.rst (rst), // input
.clk (mclk), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (phy_16bit_addr), // output[15:0]
.data (phy_16bit_data), // output[31:0]
.we (phy_16bit_we) // output
);
wire set_patterns;
wire set_patterns_tri;
wire set_wbuf_delay;
wire set_extra;
wire control_status_we; // share with write delay (8-but)?
wire [7:0] contral_status_data;
assign set_patterns= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_16BIT_PATTERNS);
assign set_patterns_tri= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_16BIT_PATTERNS_TRI);
assign set_wbuf_delay= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_16BIT_WBUF_DELAY);
assign set_extra= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_16BIT_EXTRA);
assign control_status_we= phy_16bit_we && (phy_16bit_addr[2:0]==MCONTR_PHY_STATUS_CNTRL);
assign contral_status_data= phy_16bit_data[7:0];
always @ (posedge mclk or posedge rst) begin
if (rst) begin
dqm_pattern <=DFLT_DQM_PATTERN;
dqs_pattern <=DFLT_DQS_PATTERN;
end else if (set_patterns) begin
dqm_pattern <= phy_16bit_data[15:8];
dqs_pattern <= phy_16bit_data[7:0];
end
if (rst) begin
dqs_tri_off_pattern[3:0] <= DFLT_DQS_TRI_OFF_PATTERN;
dqs_tri_on_pattern[3:0] <= DFLT_DQS_TRI_ON_PATTERN;
dq_tri_off_pattern[3:0] <= DFLT_DQ_TRI_OFF_PATTERN;
dq_tri_on_pattern[3:0] <= DFLT_DQ_TRI_ON_PATTERN;
end else if (set_patterns_tri) begin
dqs_tri_off_pattern[3:0] <= phy_16bit_data[15:12];
dqs_tri_on_pattern[3:0] <= phy_16bit_data[11: 8];
dq_tri_off_pattern[3:0] <= phy_16bit_data[ 7: 4];
dq_tri_on_pattern[3:0] <= phy_16bit_data[ 3: 0];
end
if (rst) wbuf_delay <= DFLT_WBUF_DELAY;
else if (set_wbuf_delay) wbuf_delay <= phy_16bit_data[ 3: 0];
if (rst) inv_clk_div <= DFLT_INV_CLK_DIV;
else if (set_extra) inv_clk_div <= phy_16bit_data[0];
end
// TODO: status
assign locked=locked_mmcm && locked_pll;
assign status_data={dly_ready,dci_ready, locked_mmcm, locked_pll, run_busy,locked,ps_rdy,ps_out[7:0]};
status_generate #(
.STATUS_REG_ADDR (MCONTR_PHY_STATUS_REG_ADDR),
.PAYLOAD_BITS (15)
) status_generate_i (
.rst (rst), // input
.clk (mclk), // input
.we (control_status_we), // input
.wd (contral_status_data), // input[7:0]
.status (status_data), // input[25:0]
.ad (status_ad), // output[7:0]
.rq (status_rq), // output
.start (status_start) // input
);
always @ (posedge mclk or posedge rst) begin
if (rst) cmd_busy <= 0;
// else if (sequence_done) cmd_busy <= 0;
else if (ddr_rst) cmd_busy <= 0; // *************** reset sequencer with DDR reset
else if (sequence_done && cmd_busy[2]) cmd_busy <= 0;
else cmd_busy <= {cmd_busy[1:0],run_seq | cmd_busy[0]};
// 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;
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.
// Fetch - command data valid
if (rst) cmd_fetch <= 0;
else cmd_fetch <= cmd_busy[0] && !pause;
if (rst) add_pause <= 0;
else add_pause <= cmd_fetch && phy_cmd_add_pause;
// Command read address
if (rst) cmd_addr <= 0;
else if (run_seq) cmd_addr <= run_addr[9:0];
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.
// 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];
// if (rst) buf_raddr <= 7'h0;
// else if (run_seq_d) buf_raddr <= 7'h0;
// 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.
if (rst) run_chn_d <= 0;
else if (run_seq) run_chn_d <= run_chn;
// if (rst) run_seq_d <= 0;
// else run_seq_d <= run_seq;
end
// re-register buffer write address to match DDR3 data
always @ (negedge mclk) begin
// buf_waddr_negedge <= buf_raddr;
buf_waddr_reset_negedge <= buf_rst_d; //buf_raddr_reset;
buf_wr_negedge <= buf_wr;
buf_wdata_negedge <= buf_wdata;
run_chn_w_d_negedge <= run_chn_w_d; //run_chn_d;
end
// Command sequence memories:
// Command sequence memory 0 ("manual"):
wire ren0=!cmd_sel && cmd_busy[0] && !pause; // cmd_busy - multibit
wire ren1= cmd_sel && cmd_busy[0] && !pause;
ram_1kx32_1kx32 #(
.REGISTERS(1) // (0) // register output
) cmd0_buf_i (
.rclk (mclk), // input
.raddr (cmd_addr), // input[9:0]
.ren (ren0), // input TODO: verify cmd_busy[0] is correct (was cmd_busy )
.regen (ren0), // input
.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 #(
.REGISTERS(1) // (0) // register output
) cmd1_buf_i (
.rclk (mclk), // input
.raddr (cmd_addr), // input[9:0]
.ren ( ren1), // input
.regen ( ren1), // input
.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]
);
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),
.SDCLK_PHASE (SDCLK_PHASE),/// debugging
.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),
.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
) phy_cmd_i (
.SDRST (SDRST), // output
.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
// .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]),
.ps_rdy (ps_rdy), // output
.ps_out (ps_out[7:0]), // output[7:0]
.phy_cmd_word (phy_cmd_word[31:0]), // input[31:0]
.phy_cmd_nop (phy_cmd_nop), // output
.phy_cmd_add_pause (phy_cmd_add_pause), // one pause cycle (for 8-bursts)
.add_pause (add_pause),
.pause_len (pause_len), // output [CMD_PAUSE_BITS-1:0]
.sequence_done (sequence_done), // output
.buf_wdata (buf_wdata[63:0]), // output[63:0]
.buf_rdata (buf_rdata[63:0]), // input[63:0]
.buf_wr (buf_wr_ndly), // output
.buf_rd (buf_rd), // output
.buf_rst (buf_rst), // reset external buffer address to page start
.cmda_en (cmda_en), // input
.ddr_rst (ddr_rst), // input
.dci_rst (dci_rst), // input
.dly_rst (dly_rst), // input
.ddr_cke (ddr_cke), // input
.inv_clk_div (inv_clk_div), // input
.dqs_pattern (dqs_pattern), // input[7:0]
.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?)
dly_16 #(2) buf_wr_dly_i (
.clk(mclk), // input
.rst(1'b0), // input
.dly(wbuf_delay[3:0]), // input[3:0]
.din({buf_rst,buf_wr_ndly}), // input
.dout({buf_rst_d, buf_wr}) // output reg
);
dly_16 #(4) buf_wchn_dly_i (
.clk(mclk), // input
.rst(1'b0), // input
.dly(wbuf_delay[3:0]-1), // input[3:0]
.din(run_chn_d), // input
.dout(run_chn_w_d) // output reg
);
//run_chn_w_d
endmodule