Loading phy/phy_top.v +159 −5 Original line number Original line Diff line number Diff line Loading @@ -24,15 +24,36 @@ module phy_top #( parameter IOSTANDARD_DQ = "SSTL15_T_DCI", parameter IOSTANDARD_DQ = "SSTL15_T_DCI", parameter IOSTANDARD_DQS = "DIFF_SSTL15_T_DCI", parameter IOSTANDARD_DQS = "DIFF_SSTL15_T_DCI", parameter IOSTANDARD_CMDA = "SSTL15", parameter IOSTANDARD_CMDA = "SSTL15", parameter IOSTANDARD_CLK = "DIFF_SSTL15", parameter SLEW_DQ = "SLOW", parameter SLEW_DQ = "SLOW", parameter SLEW_DQS = "SLOW", parameter SLEW_DQS = "SLOW", parameter SLEW_CMDA = "SLOW", parameter SLEW_CMDA = "SLOW", parameter SLEW_CLK = "SLOW", parameter IBUF_LOW_PWR = "TRUE", parameter IBUF_LOW_PWR = "TRUE", parameter IODELAY_GRP = "IODELAY_MEMORY", parameter IODELAY_GRP = "IODELAY_MEMORY", parameter real REFCLK_FREQUENCY = 300.0, parameter real REFCLK_FREQUENCY = 300.0, parameter HIGH_PERFORMANCE_MODE = "FALSE", 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 [ADDRESS_NUMBER-1:0] ddr3_a, // output address ports (14:0) for 4Gb device output [2:0]ddr3_ba, // output bank address ports output [2:0]ddr3_ba, // output bank address ports output ddr3_we, // output WE port output ddr3_we, // output WE port Loading @@ -49,8 +70,10 @@ module phy_top #( inout dqsu, // UDQS I/O pad inout dqsu, // UDQS I/O pad inout ndqsu, // ~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_in, // master input clock, initially assuming 100MHz input clk_div, // free-running half clk frequency, front aligned to clk (shared for R/W) 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 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 input [2*ADDRESS_NUMBER-1:0] in_a, // input address, 2 bits per signal (first, second) (29:0) for 4Gb device Loading @@ -77,7 +100,10 @@ module phy_top #( input [7:0] dly_data, // delay value (3 LSB - fine delay) input [7:0] dly_data, // delay value (3 LSB - fine delay) input [6:0] dly_addr, // select which delay to program 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_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; reg rst=1'b0; always @(posedge clk or posedge rst_in) begin always @(posedge clk or posedge rst_in) begin Loading @@ -87,7 +113,11 @@ module phy_top #( wire ld_data_l = (dly_addr[6:5] == 2'h0) && ld_delay ; 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_data_h = (dly_addr[6:5] == 2'h1) && ld_delay ; wire ld_cmda = (dly_addr[6:5] == 2'h2) && 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 #( cmd_addr #( .IODELAY_GRP(IODELAY_GRP), .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD_CMDA), .IOSTANDARD(IOSTANDARD_CMDA), Loading Loading @@ -183,6 +213,130 @@ module phy_top #( .ld_delay (ld_data_h), // load delay data to selected iodelayl (clk_div synchronous) .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 .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 endmodule Loading
phy/phy_top.v +159 −5 Original line number Original line Diff line number Diff line Loading @@ -24,15 +24,36 @@ module phy_top #( parameter IOSTANDARD_DQ = "SSTL15_T_DCI", parameter IOSTANDARD_DQ = "SSTL15_T_DCI", parameter IOSTANDARD_DQS = "DIFF_SSTL15_T_DCI", parameter IOSTANDARD_DQS = "DIFF_SSTL15_T_DCI", parameter IOSTANDARD_CMDA = "SSTL15", parameter IOSTANDARD_CMDA = "SSTL15", parameter IOSTANDARD_CLK = "DIFF_SSTL15", parameter SLEW_DQ = "SLOW", parameter SLEW_DQ = "SLOW", parameter SLEW_DQS = "SLOW", parameter SLEW_DQS = "SLOW", parameter SLEW_CMDA = "SLOW", parameter SLEW_CMDA = "SLOW", parameter SLEW_CLK = "SLOW", parameter IBUF_LOW_PWR = "TRUE", parameter IBUF_LOW_PWR = "TRUE", parameter IODELAY_GRP = "IODELAY_MEMORY", parameter IODELAY_GRP = "IODELAY_MEMORY", parameter real REFCLK_FREQUENCY = 300.0, parameter real REFCLK_FREQUENCY = 300.0, parameter HIGH_PERFORMANCE_MODE = "FALSE", 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 [ADDRESS_NUMBER-1:0] ddr3_a, // output address ports (14:0) for 4Gb device output [2:0]ddr3_ba, // output bank address ports output [2:0]ddr3_ba, // output bank address ports output ddr3_we, // output WE port output ddr3_we, // output WE port Loading @@ -49,8 +70,10 @@ module phy_top #( inout dqsu, // UDQS I/O pad inout dqsu, // UDQS I/O pad inout ndqsu, // ~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_in, // master input clock, initially assuming 100MHz input clk_div, // free-running half clk frequency, front aligned to clk (shared for R/W) 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 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 input [2*ADDRESS_NUMBER-1:0] in_a, // input address, 2 bits per signal (first, second) (29:0) for 4Gb device Loading @@ -77,7 +100,10 @@ module phy_top #( input [7:0] dly_data, // delay value (3 LSB - fine delay) input [7:0] dly_data, // delay value (3 LSB - fine delay) input [6:0] dly_addr, // select which delay to program 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_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; reg rst=1'b0; always @(posedge clk or posedge rst_in) begin always @(posedge clk or posedge rst_in) begin Loading @@ -87,7 +113,11 @@ module phy_top #( wire ld_data_l = (dly_addr[6:5] == 2'h0) && ld_delay ; 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_data_h = (dly_addr[6:5] == 2'h1) && ld_delay ; wire ld_cmda = (dly_addr[6:5] == 2'h2) && 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 #( cmd_addr #( .IODELAY_GRP(IODELAY_GRP), .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD_CMDA), .IOSTANDARD(IOSTANDARD_CMDA), Loading Loading @@ -183,6 +213,130 @@ module phy_top #( .ld_delay (ld_data_h), // load delay data to selected iodelayl (clk_div synchronous) .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 .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 endmodule