Commit d6733779 authored by Andrey Filippov's avatar Andrey Filippov

just a snapshot

parent c7b65d94
......@@ -111,10 +111,12 @@ generate
.rst(rst),
.dci_disable(dci_disable_dq_r), // disable DCI termination during writes and idle
.dly_data(dly_data_r), // delay value (3 LSB - fine delay)
.din(din_r[4*i+3:4*i]) , // parallel data to be sent out
.din({din_r[i+24],din_r[i+16],din_r[i+8],din_r[i]}) , // parallel data to be sent out
// .din(din_r[4*i+3:4*i]) , // parallel data to be sent out
// .din(din_r[4*i+3-:4]) , // parallel data to be sent out
.tin(tin_dq_r), // tristate for data out (sent out earlier than data!)
.dout(dout[4*i+3:4*i]), // parallel data received from DDR3 memory
.dout({dout[i+24],dout[i+16],dout[i+8],dout[i]}), // parallel data received from DDR3 memory
// .dout(dout[4*i+3:4*i]), // parallel data received from DDR3 memory
.set_odelay(set_r), // clk_div synchronous load odelay value from dly_data
.ld_odelay(ld_odly[i]), // clk_div synchronous set odealy value from loaded
.set_idelay(set_r), // clk_div synchronous load idelay value from dly_data
......
......@@ -49,7 +49,7 @@ module cmd_addr #(
input in_tri, // tristate command/address outputs - same timing, but no odelay
input [7:0] dly_data, // delay value (3 LSB - fine delay)
input [4:0] dly_addr, // select which delay to program
input ld_delay, // load delay data to selected iodelayl (clk_iv synchronous)
input ld_delay, // load delay data to selected iodelayl (clk_div synchronous)
input set // clk_div synchronous set all delays from previously loaded values
);
reg [2*ADDRESS_NUMBER-1:0] in_a_r=0;
......@@ -110,7 +110,7 @@ generate
.clk_div(clk_div), // free-running half clk frequency, front aligned to clk (shared for R/W)
.rst(rst),
.dly_data(dly_data_r[7:0]), // delay value (3 LSB - fine delay)
.din(in_a_r[2*i+1:2*i]), // parallel data to be sent out
.din({in_a_r[ADDRESS_NUMBER+i],in_a_r[i]}), // parallel data to be sent out
// .tin(in_tri_r[1:0]), // tristate for data out (sent out earlier than data!)
.tin(in_tri_r), // tristate for data out (sent out earlier than data!)
.set_delay(set_r), // clk_div synchronous load odelay value from dly_data
......@@ -132,7 +132,7 @@ endgenerate
.clk_div(clk_div),
.rst(rst),
.dly_data(dly_data_r[7:0]),
.din(in_ba_r[1:0]),
.din({in_ba_r[3],in_ba_r[0]}),
// .tin(in_tri_r[1:0]),
.tin(in_tri_r),
.set_delay(set_r),
......@@ -150,7 +150,7 @@ endgenerate
.clk_div(clk_div),
.rst(rst),
.dly_data(dly_data_r[7:0]),
.din(in_ba_r[3:2]),
.din({in_ba_r[4],in_ba_r[1]}),
// .tin(in_tri_r[1:0]),
.tin(in_tri_r),
.set_delay(set_r),
......@@ -168,7 +168,7 @@ endgenerate
.clk_div(clk_div),
.rst(rst),
.dly_data(dly_data_r[7:0]),
.din(in_ba_r[5:4]),
.din({in_ba_r[5],in_ba_r[2]}),
// .tin(in_tri_r[1:0]),
.tin(in_tri_r),
.set_delay(set_r),
......
/*******************************************************************************
* Module: ddr3c16
* Date:2014-05-16
* Author: Andrey Filippov
* Description: ddr3 controller, 16 channel
*
* Copyright (c) 2014 Elphel, Inc.
* ddr3c16.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.
*
* ddr3c16.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/> .
*******************************************************************************/
`timescale 1ns/1ps
module ddr3c16 #(
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,
parameter ICLK_PHASE = 0.000,
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,
parameter DQSTRI_FIRST= 4'h3, // DQS tri-state control word, first when enabling output
parameter DQSTRI_LAST= 4'hc, // DQS tri-state control word, first after disabling output
parameter DQTRI_FIRST= 4'h7, // DQ tri-state control word, first when enabling output
parameter DQTRI_LAST= 4'he // DQ tri-state control word, first after disabling output
)(
// DDR3 interface
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
inout [15:0] SDD, // DQ I/O pads
inout SDDML, // LDM I/O pad (actually only output)
inout DQSL, // LDQS I/O pad
inout NDQSL, // ~LDQS I/O pad
inout SDDMU, // UDM I/O pad (actually only output)
inout DQSU, // UDQS I/O pad
inout NDQSU, // ~UDQS I/O pad
// clocks, reset
input clk_in,
input rst_in,
output mclk, // global clock, half DDR3 clock, synchronizes all I/O thorough the command port
// command port 0 (filled by software - 32w->64r) - used for mode set, refresh, write levelling, ...
input cmd0_we,
input [9:0] cmd0_addr,
input [31:0] cmd0_data,
// TODO: add automatic command port1 , filled by the PL, 36w 36r, used for actual page R/W
input cmd1_we,
input [9:0] cmd1_addr,
input [35:0] cmd1_data,
// Controller run interface, posedge mclk
input [10:0] run_addr, // controller sequencer start address (0..11'h1ff - cmd0, 11'h400..11'h7ff - cmd1)
input [3:0] run_chn, // data channel to use
input run_seq, // start controller sequence
output run_done, // controller sequence finished
// 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
output locked,
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
input cmda_tri, // tristate command and address lines // not likely to be used
input inv_clk_div,
input [7:0] dqs_pattern, // 8'h55
input [7:0] dqm_pattern // 8'h00
);
localparam ADDRESS_NUMBER = 15;
wire [35:0] phy_cmd; // input[35:0]
wire [6:0] buf_addr; // output[6:0]
wire [63:0] buf_wdata; // output[63:0]
wire [63:0] buf_rdata; // input[63:0]
wire buf_wr; // output
wire buf_rd; // output
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),
.ICLK_PHASE (ICLK_PHASE),
.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_cmd_i (
.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
.ps_rdy (ps_rdy), // output
.ps_out (ps_out[7:0]), // output[7:0]
.phy_cmd (phy_cmd[35:0]), // input[35:0]
.buf_addr (buf_addr[6:0]), // output[6:0]
.buf_wdata (buf_wdata[63:0]), // output[63:0]
.buf_rdata (buf_rdata[63:0]), // input[63:0]
.buf_wr (buf_wr), // output
.buf_rd (buf_rd), // output
.cmda_tri (cmda_tri), // input
.inv_clk_div (inv_clk_div), // input
.dqs_pattern (dqs_pattern), // input[7:0]
.dqm_pattern (dqm_pattern) // input[7:0]
);
endmodule
/*******************************************************************************
* Module: phy_cmd
* Date:2014-05-15
* Author: Andrey Filippov
* Description: Executes a stream of commands to DDR3 phy at 1/2 ddr3 clock, global
* (also proveides r/w interface to the x64 external buffer)
*
* Copyright (c) 2014 Elphel, Inc.
* 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/> .
*******************************************************************************/
`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 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,
parameter ICLK_PHASE = 0.000,
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
)(
// DDR3 interface
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
inout [15:0] SDD, // DQ I/O pads
inout SDDML, // LDM I/O pad (actually only output)
inout DQSL, // LDQS I/O pad
inout NDQSL, // ~LDQS I/O pad
inout SDDMU, // UDM I/O pad (actually only output)
inout DQSU, // UDQS I/O pad
inout NDQSU, // ~UDQS I/O pad
// clocks, reset
input clk_in,
input rst_in,
output mclk, // global clock, half DDR3 clock, synchronizes all I/O thorough the command port
// 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
output locked,
output ps_rdy,
output [PHASE_WIDTH-1:0] ps_out,
// command port
input [35:0] phy_cmd,
// external memory buffer (cs- channel select, high addresses- page addresses are decoded externally)
output [ 6:0] buf_addr,
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!)
output buf_rd, // read buffer (ready next cycle)
// extras
input cmda_tri, // tristate command and address lines // not likely to be used
input inv_clk_div,
input [7:0] dqs_pattern, // 8'h55
input [7:0] dqm_pattern // 8'h00
);
localparam DQSTRI_FIRST= 4'h3; // DQS tri-state control word, first when enabling output
localparam DQSTRI_LAST= 4'hc; // DQS tri-state control word, first after disabling output
localparam DQTRI_FIRST= 4'h7; // DQ tri-state control word, first when enabling output
localparam DQTRI_LAST= 4'he; // DQ tri-state control word, first after disabling output
// 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;
wire [ 2:0] phy_rcw_in; // {ras,cas,we}
wire phy_odt_in; // may be optimized?
wire phy_cke_in; // may be optimized?
wire phy_sel_in; // fitst/second half-cycle, oter will be nop (cke+odt applicable to both)
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_in; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
wire [ 6:0] phy_buf_addr; // connect to extrenal buffer
wire phy_buf_wr; // connect to extrenal buffer
wire phy_buf_rd; // connect to extrenal buffer
// wire clk;
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?
wire [1:0] phy_cke; // may be optimized?
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_locked;
wire phy_ps_rdy;
wire [PHASE_WIDTH-1:0] phy_ps_out;
reg locked_r1,locked_r2;
reg ps_rdy_r1,ps_rdy_r2;
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
// output [63:0] buf_wdata, // data to be written to the buffer (from DDR3)
assign {
phy_addr_in,
phy_bank_in,
phy_rcw_in, // {ras,cas,we}
phy_odt_in, // may be optimized?
phy_cke_in, // may be optimized?
phy_sel_in, // fitst/second half-cycle, oter will be nop (cke+odt applicable to both)
phy_dq_tri_in, // tristate DQ lines (internal timing sequencer for 0->1 and 1->0)
phy_dqs_tri_in, // tristate DQS lines (internal timing sequencer for 0->1 and 1->0)
phy_dci_in, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
phy_buf_addr, // connect to extrenal buffer
phy_buf_wr, // connect to extrenal buffer
phy_buf_rd // connect to extrenal buffer
} = phy_cmd;
assign buf_addr = phy_buf_addr;
assign buf_wr = phy_buf_wr;
assign buf_rd = phy_buf_rd;
assign phy_addr= {phy_addr_in,phy_addr_in}; // also provides pause length when the command is NOP
assign phy_bank= {phy_bank_in,phy_bank_in};
assign phy_rcw= {phy_sel_in?phy_rcw_in:3'h0, phy_sel_in?3'h0:phy_rcw_in}; // {ras,cas,we}
assign phy_odt= {phy_odt_in,phy_odt_in}; // may be optimized?
assign phy_cke= {phy_cke_in,phy_cke_in}; // may be optimized?
// 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}}}:
(dq_tri_prev?{DQTRI_FIRST,DQTRI_FIRST}:{DQTRI_LAST,DQTRI_LAST});
// 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}}}:
(dqs_tri_prev?{DQSTRI_FIRST,DQSTRI_FIRST}:{DQSTRI_LAST,DQSTRI_LAST});
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)
assign phy_dci_dis_dqs = phy_dci_in; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
assign locked = locked_r2;
assign ps_rdy = ps_rdy_r2;
assign ps_out = ps_out_r2;
assign buf_wdata[63:0] = phy_rdata_r[63:0];
always @ (posedge mclk) begin
dqs_tri_prev <= phy_dqs_tri_in;
dq_tri_prev <= phy_dq_tri_in;
end
// cross clock boundary posedge mclk -> posedge clk_div (mclk is later than clk_div)
always @ (posedge clk_div or posedge rst_in) begin
if (rst_in) begin
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
locked_r1 <= phy_locked;
ps_rdy_r1 <= phy_ps_rdy;
ps_out_r1 <= phy_ps_out;
end
always @ (posedge mclk) begin
locked_r2 <= locked_r1;
ps_rdy_r2 <= ps_rdy_r1;
ps_out_r2 <= ps_out_r1;
end
always @ (negedge mclk) begin
phy_rdata_r[63:0] <= phy_rdata[63:0];
end
/*
phy_rdata
wire phy_locked;
wire phy_ps_rdy;
wire [PHASE_WIDTH-1:0] phy_ps_out;
output locked,
output ps_rdy,
output [PHASE_WIDTH-1:0] ps_out,
*/
phy_top #(
.IOSTANDARD_DQ ("SSTL15_T_DCI"),
.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),
.CLKFBOUT_MULT_REF(CLKFBOUT_MULT_REF),
.CLKFBOUT_DIV_REF (CLKFBOUT_DIV_REF),
.DIVCLK_DIVIDE (DIVCLK_DIVIDE),
.CLKFBOUT_PHASE (CLKFBOUT_PHASE),
.ICLK_PHASE (ICLK_PHASE),
.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 (
.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 (clk), // output
.clk (), // output
.clk_div (clk_div), // output
.mclk (mclk), // output
.rst_in (rst_in), // input
.in_a (phy_addr[2*ADDRESS_NUMBER-1:0]), // input[29:0]
.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_pattern[7:0]), // 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 (phy_locked), // output
.ps_rdy (phy_ps_rdy), // output
.ps_out (phy_ps_out) // output[7:0]
);
endmodule
......@@ -46,7 +46,7 @@ module phy_top #(
parameter ICLK_PHASE = 0.000,
parameter CLK_PHASE = 0.000,
parameter CLK_DIV_PHASE = 0.000,
parameter MCLK_PHASE = 0.000,
parameter MCLK_PHASE = 90.000,
parameter REF_JITTER1 = 0.010,
parameter SS_EN = "FALSE",
parameter SS_MODE = "CENTER_HIGH",
......@@ -100,7 +100,7 @@ module phy_top #(
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_iv synchronous)
input ld_delay, // load delay data to selected iodelayl (clk_div synchronous)
input set, // clk_div synchronous set all delays from previously loaded values
output locked,
output ps_rdy,
......@@ -148,7 +148,7 @@ module phy_top #(
.in_tri (in_tri), // tristate command/address outputs - same timing, but no odelay
.dly_data (dly_data[7:0]), // delay value (3 LSB - fine delay)
.dly_addr (dly_addr[4:0]), // select which delay to program
.ld_delay (ld_cmda), // load delay data to selected iodelayl (clk_iv synchronous)
.ld_delay (ld_cmda), // load delay data to selected iodelayl (clk_div synchronous)
.set (set) // clk_div synchronous set all delays from previously loaded values
);
......
......@@ -105,7 +105,7 @@ module test_phy_top_01#(
reg dci_disable_dq; // disable DCI termination during writes and idle for dq and dm signals
reg [7:0] dly_data; // delay value (3 LSB - fine delay)
reg [6:0] dly_addr; // select which delay to program
reg ld_delay; // load delay data to selected iodelayl (clk_iv synchronous)
reg ld_delay; // load delay data to selected iodelayl (clk_div synchronous)
reg set; // clk_div synchronous set all delays from previously loaded values
reg [63:0] dout_r;
......
......@@ -142,12 +142,12 @@ module ram_1kx32_1kx32
.DIBDI(data_in[31:0]), // Port B data/MSB data[31:0], input
.DIPBDIP(4'b0), // Port B parity/MSB parity[3:0], input
.ADDRBWRADDR({1'b1,waddr[9:0],5'b11111}), // Port B (write port in SDP) address [15:0]. used from [14] down, unused should be high, input
.CLKBWRCLK(wclk), // Port B (read port in SDP) clock, input
.ENBWREN(we), // Port B (read port in SDP) Enable, input
.REGCEB(1'b0), // Port B (read port in SDP) register enable, input
.RSTRAMB(1'b0), // Port B (read port in SDP) set/reset, input
.RSTREGB(1'b0), // Port B (read port in SDP) register set/reset, input
.WEBWE({4'b0,web[3:0]}), // Port B (read port in SDP) Write Enable[7:0], input
.CLKBWRCLK(wclk), // Port B (write port in SDP) clock, input
.ENBWREN(we), // Port B (write port in SDP) Enable, input
.REGCEB(1'b0), // Port B (write port in SDP) register enable, input
.RSTRAMB(1'b0), // Port B (write port in SDP) set/reset, input
.RSTREGB(1'b0), // Port B (write port in SDP) register set/reset, input
.WEBWE({4'b0,web[3:0]}), // Port B (write port in SDP) Write Enable[7:0], input
// Error correction circuitry
.SBITERR(), // Single bit error status, output
.DBITERR(), // Double bit error status, output
......
/*******************************************************************************
* Copyright (c) 2014 Elphel, Inc.
* ram_1kx32w_512x64r.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.
*
* ram_1kx32w_512x64r.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/>.
*******************************************************************************/
/*
Address/data widths
Connect unused data to 1b0, unused addresses - to 1'b1
RAMB18E1 in True Dual Port (TDP) Mode - each port individually
+-----------+---------+---------+---------+
|Data Width | Address | Data | Parity |
+-----------+---------+---------+---------+
| 1 | A[13:0] | D[0] | --- |
| 2 | A[13:1] | D[1:0] | --- |
| 4 | A[13:2] | D[3:0[ | --- |
| 9 | A[13:3] | D[7:0] | DP[0] |
| 18 | A[13:4] | D[15:0] | DP[1:0] |
+-----------+---------+---------+---------+
RAMB18E1 in Simple Dual Port (SDP) Mode
one of the ports (r or w) - 32/36 bits, other - variable
+------------+---------+---------+---------+
|Data Widths | Address | Data | Parity |
+------------+---------+---------+---------+
| 32/ 1 | A[13:0] | D[0] | --- |
| 32/ 2 | A[13:1] | D[1:0] | --- |
| 32/ 4 | A[13:2] | D[3:0[ | --- |
| 36/ 9 | A[13:3] | D[7:0] | DP[0] |
| 36/ 18 | A[13:4] | D[15:0] | DP[1:0] |
| 36/ 36 | A[13:5] | D[31:0] | DP[3:0] |
+------------+---------+---------+---------+
RAMB36E1 in True Dual Port (TDP) Mode - each port individually
+-----------+---------+---------+---------+
|Data Width | Address | Data | Parity |
+-----------+---------+---------+---------+
| 1 | A[14:0] | D[0] | --- |
| 2 | A[14:1] | D[1:0] | --- |
| 4 | A[14:2] | D[3:0[ | --- |
| 9 | A[14:3] | D[7:0] | DP[0] |
| 18 | A[14:4] | D[15:0] | DP[1:0] |
| 36 | A[14:5] | D[31:0] | DP[3:0] |
|1(Cascade) | A[15:0] | D[0] | --- |
+-----------+---------+---------+---------+
RAMB36E1 in Simple Dual Port (SDP) Mode
one of the ports (r or w) - 64/72 bits, other - variable
+------------+---------+---------+---------+
|Data Widths | Address | Data | Parity |
+------------+---------+---------+---------+
| 64/ 1 | A[14:0] | D[0] | --- |
| 64/ 2 | A[14:1] | D[1:0] | --- |
| 64/ 4 | A[14:2] | D[3:0[ | --- |
| 64/ 9 | A[14:3] | D[7:0] | DP[0] |
| 64/ 18 | A[14:4] | D[15:0] | DP[1:0] |
| 64/ 36 | A[14:5] | D[31:0] | DP[3:0] |
| 64/ 72 | A[14:6] | D[63:0] | DP[7:0] |
+------------+---------+---------+---------+
*/
module ram_1kx32w_512x64r
#(
parameter integer registers = 0 // 1 - registered output
)
(
input rclk, // clock for read port
input [ 8:0] raddr, // read address
input ren, // read port enable
input regen, // output register enable
output [63:0] data_out, // data out
input wclk, // clock for read port
input [ 9:0] waddr, // write address
input we, // write port enable
input [ 3:0] web, // write byte enable
input [31:0] data_in // data out
);
RAMB36E1
#(
.RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE"
.RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE"
.DOA_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36)
.DOB_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36)
.RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER"
.RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER"
.READ_WIDTH_A(72), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used)
.READ_WIDTH_B(0), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used)
.WRITE_WIDTH_A(0), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used)
.WRITE_WIDTH_B(36), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used)
.RAM_MODE("SDP"), // Valid "TDP" (true dual-port) and "SDP" - simple dual-port