Commit a0c1b572 authored by Andrey Filippov's avatar Andrey Filippov

more code for ddr3 phy

parent c73e99f3
......@@ -24,15 +24,36 @@ module phy_top #(
parameter IOSTANDARD_DQ = "SSTL15_T_DCI",
parameter IOSTANDARD_DQS = "DIFF_SSTL15_T_DCI",
parameter IOSTANDARD_CMDA = "SSTL15",
parameter IOSTANDARD_CLK = "DIFF_SSTL15",
parameter SLEW_DQ = "SLOW",
parameter SLEW_DQS = "SLOW",
parameter SLEW_CMDA = "SLOW",
parameter SLEW_CLK = "SLOW",
parameter IBUF_LOW_PWR = "TRUE",
parameter IODELAY_GRP = "IODELAY_MEMORY",
parameter real REFCLK_FREQUENCY = 300.0,
parameter HIGH_PERFORMANCE_MODE = "FALSE",
parameter integer ADDRESS_NUMBER= 15
parameter integer ADDRESS_NUMBER= 15,
parameter PHASE_WIDTH = 8,
parameter BANDWIDTH = "OPTIMIZED",
// Assuming 100MHz input clock, 800MHz Fvco, 400MHz clk, 200MHz clk_div, 200MHz mclk
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 CLKOUT0_PHASE = 0.000,
parameter CLKOUT1_PHASE = 0.000,
parameter CLKOUT2_PHASE = 0.000,
parameter CLKOUT3_PHASE = 0.000,
parameter REF_JITTER1 = 0.010,
parameter SS_EN = "FALSE",
parameter SS_MODE = "CENTER_HIGH",
parameter SS_MOD_PERIOD = 10000
)(
output ddr3_clk, // DDR3 clock differential output, positive
output ddr3_nclk,// DDR3 clock differential output, negative
output [ADDRESS_NUMBER-1:0] ddr3_a, // output address ports (14:0) for 4Gb device
output [2:0]ddr3_ba, // output bank address ports
output ddr3_we, // output WE port
......@@ -49,8 +70,10 @@ module phy_top #(
inout dqsu, // UDQS I/O pad
inout ndqsu, // ~UDQS I/O pad
input clk, // free-running system clock, same frequency as iclk (shared for R/W)
input clk_div, // free-running half clk frequency, front aligned to clk (shared for R/W)
input clk_in, // master input clock, initially assuming 100MHz
output clk, // free-running system clock, same frequency as iclk (shared for R/W), BUFR output
output clk_div, // free-running half clk frequency, front aligned to clk (shared for R/W), BUFR output
output mclk, // same as clk_div, through separate BUFG and static phase adjust
input rst_in, // reset delays/serdes
input [2*ADDRESS_NUMBER-1:0] in_a, // input address, 2 bits per signal (first, second) (29:0) for 4Gb device
......@@ -77,7 +100,10 @@ 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 set // clk_div synchronous set all delays from previously loaded values
input set, // clk_div synchronous set all delays from previously loaded values
output locked,
output ps_rdy,
output [PHASE_WIDTH-1:0] ps_out
);
reg rst=1'b0;
always @(posedge clk or posedge rst_in) begin
......@@ -87,7 +113,11 @@ module phy_top #(
wire ld_data_l = (dly_addr[6:5] == 2'h0) && ld_delay ;
wire ld_data_h = (dly_addr[6:5] == 2'h1) && ld_delay ;
wire ld_cmda = (dly_addr[6:5] == 2'h2) && ld_delay ;
wire ld_mmcm= (dly_addr[6:0] == 7'h60) && ld_delay ;
wire clkfb_ref, clk_ref_pre;
wire clk_ref; // 200MHz/300Mhz to calibrate I/O delays
wire locked_mmcm,locked_pll, dly_ready;
assign locked=locked_mmcm && locked_pll && dly_ready; // both PLL ready, I/O delay calibrated
cmd_addr #(
.IODELAY_GRP(IODELAY_GRP),
.IOSTANDARD(IOSTANDARD_CMDA),
......@@ -183,6 +213,130 @@ module phy_top #(
.ld_delay (ld_data_h), // load delay data to selected iodelayl (clk_div synchronous)
.set (set) // clk_div synchronous set all delays from previously loaded values
);
//ddr3_clk
wire iclk; // BUFIO
oddr_ds #(
.IOSTANDARD(IOSTANDARD_CLK),
.SLEW(SLEW_CLK)
) oddr_ds_i (
.clk(iclk), // input
.ce(1'b1), // input
.rst(1'b0), // input
.set(1'b0), // input
.din(2'b01), // input[1:0]
.dq(ddr3_clk), // output
.ndq(ddr3_nclk) // output
);
// Clocks: MMCM is used to generate ddr3 differential clock (no dynamic phase shift),
// clk - write bit clock, phase dynamically adjusted, BUFR (initially 400MHz)
// clk_div half bit frequency clock, phase dynamically adjusted, BUFR. Used also for delay/phase control (200MHz)
// mclk - same frequency as clk_div (same dynamic phase adjust), but with BUFG to be used in other regions. Phase to be
// statically adjusted for clock boundary crossing
// Phase control included, allowing setting phase in +/- 127 steps, each 1/56 of 1/Fvco (~22ps for Fvco=800MHz)
wire clk_pre, clk_div_pre, iclk_pre, mclk_pre, clk_fb;
BUFR clk_bufr_i (.O(clk), .CE(), .CLR(), .I(clk_pre));
BUFR clk_div_bufr_i (.O(clk_div), .CE(), .CLR(), .I(clk_div_pre));
BUFIO iclk_bufio_i (.O(iclk), .I(iclk_pre) );
BUFIO clk_ref_i (.O(clk_ref), .I(clk_ref_pre));
BUFG mclk_i (.O(mclk),.I(mclk_pre) );
/* Instance template for module mmcm_phase_cntr */
mmcm_phase_cntr #(
.PHASE_WIDTH (PHASE_WIDTH),
.CLKIN_PERIOD (CLKIN_PERIOD),
.BANDWIDTH (BANDWIDTH),
.CLKFBOUT_MULT_F (CLKFBOUT_MULT),
.DIVCLK_DIVIDE (DIVCLK_DIVIDE),
.CLKFBOUT_PHASE (CLKFBOUT_PHASE),
.CLKOUT0_PHASE (CLKOUT0_PHASE),
.CLKOUT1_PHASE (CLKOUT1_PHASE),
.CLKOUT2_PHASE (CLKOUT2_PHASE),
.CLKOUT3_PHASE (CLKOUT3_PHASE),
// .CLKOUT4_PHASE (0.000),
// .CLKOUT5_PHASE (0.000),
// .CLKOUT6_PHASE (0.000),
.CLKFBOUT_USE_FINE_PS ("FALSE"),
.CLKOUT0_USE_FINE_PS ("FALSE"),
.CLKOUT1_USE_FINE_PS ("TRUE"),
.CLKOUT2_USE_FINE_PS ("TRUE"),
.CLKOUT3_USE_FINE_PS ("TRUE"),
// .CLKOUT4_USE_FINE_PS("FALSE"),
// .CLKOUT5_USE_FINE_PS("FALSE"),
// .CLKOUT6_USE_FINE_PS("FALSE"),
.CLKOUT0_DIVIDE_F (2.000),
.CLKOUT1_DIVIDE (2),
.CLKOUT2_DIVIDE (4),
.CLKOUT3_DIVIDE (4),
// .CLKOUT4_DIVIDE(1),
// .CLKOUT5_DIVIDE(1),
// .CLKOUT6_DIVIDE(1),
.COMPENSATION ("ZHOLD"),
.REF_JITTER1 (REF_JITTER1),
// .REF_JITTER2(0.010),
.SS_EN (SS_EN),
.SS_MODE (SS_MODE),
.SS_MOD_PERIOD (SS_MOD_PERIOD),
.STARTUP_WAIT ("FALSE")
) mmcm_phase_cntr_i (
.clkin (clk_in), // input
.clkfbin (clk_fb), // input
.rst (rst), // input
.pwrdwn (1'b0), // input
.psclk (clk_div), // input
.ps_we (ld_mmcm), // input
.ps_din (dly_data), // input[7:0]
.ps_ready (ps_rdy), // output
.ps_dout (ps_out), // output[7:0] reg
.clkout0 (iclk_pre), // output
.clkout1 (clk_pre), // output
.clkout2 (clk_div_pre), // output
.clkout3 (mclk_pre), // output
.clkout4(), // output
.clkout5(), // output
.clkout6(), // output
.clkout0b(), // output
.clkout1b(), // output
.clkout2b(), // output
.clkout3b(), // output
.clkfbout(clk_fb), // output
.clkfboutb(), // output
.locked(locked_mmcm) // output
);
// Generate reference clock for the I/O delays
/*
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
Instance template for module pll_base */
pll_base #(
.CLKIN_PERIOD(CLKIN_PERIOD),
.BANDWIDTH("OPTIMIZED"),
.CLKFBOUT_MULT(CLKFBOUT_MULT_REF),
.CLKOUT0_DIVIDE(CLKFBOUT_DIV_REF),
.REF_JITTER1(0.010),
.STARTUP_WAIT("FALSE")
) pll_base_i (
.clkin(clk_in), // input
.clkfbin(clkfb_ref), // input
.rst(rst), // input
.pwrdwn(1'b0), // input
.clkout0(clk_ref_pre), // output
.clkout1(), // output
.clkout2(), // output
.clkout3(), // output
.clkout4(), // output
.clkout5(), // output
.clkfbout(clkfb_ref), // output
.locked(locked_pll) // output
);
// Does it need to be re-calibrated periodically?
idelay_ctrl# (
.IODELAY_GRP("IODELAY_MEMORY")
) idelay_ctrl_i (
.refclk(clk_ref),
.rst(rst),
.rdy(dly_ready)
);
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment