Loading phy/byte_lane.v +3 −3 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ * Module: byte_lane * Date:2014-04-26 * Author: Andrey Filippov * Description: DDR3 byte lane, ingluding DQS I/O, 8xDQ I/O and DM output * Description: DDR3 byte lane, including DQS I/O, 8xDQ I/O and DM output * * Copyright (c) 2014 Elphel, Inc. * byte_lane.v is free software; you can redistribute it and/or modify Loading Loading @@ -44,7 +44,7 @@ module byte_lane #( input [3:0] tin_dq, // tristate for data out (sent out earlier than data!) and dm input [3:0] din_dqs, // parallel data to be sent out over DQS input [3:0] tin_dqs, // tristate for DQS out (sent out earlier than data!) output [31:0] dout, // parallel data received from DDR3 memory, 4 bits per DG I/O output [31:0] dout, // parallel data received from DDR3 memory, 4 bits per DQ I/O 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) Loading Loading @@ -91,7 +91,7 @@ end generate genvar i; for (i=0; i<7; i=i+1) begin: dq_block for (i=0; i < 8; i=i+1) begin: dq_block dq_single #( .IODELAY_GRP(IODELAY_GRP), .IBUF_LOW_PWR(IBUF_LOW_PWR), Loading phy/cmd_addr.v 0 → 100644 +259 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: cmd_addr * Date:2014-04-26 * Author: Andrey Filippov * Description: DDR3 command/address signals * * Copyright (c) 2014 Elphel, Inc. * cmd_addr.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. * * cmd_addr.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 cmd_addr #( parameter IODELAY_GRP = "IODELAY_MEMORY", parameter IOSTANDARD = "SSTL15", parameter SLEW = "SLOW", parameter real REFCLK_FREQUENCY = 300.0, parameter HIGH_PERFORMANCE_MODE = "FALSE", parameter ADDRESS_NUMBER= 15 )( 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 output ddr3_ras, // output RAS port output ddr3_cas, // output CAS port output ddr3_cke, // output Clock Enable port output ddr3_odt, // output ODT port 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 rst, // 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 [5:0] in_ba, // input bank address, 2 bits per signal (first, second) input [1:0] in_we, // input WE, 2 bits (first, second) input [1:0] in_ras, // input RAS, 2 bits (first, second) input [1:0] in_cas, // input CAS, 2 bits (first, second) input [1:0] in_cke, // input CKE, 2 bits (first, second) input [1:0] in_odt, // input ODT, 2 bits (first, second) input [1:0] 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 set // clk_div synchronous set all delays from previously loaded values ); reg [2*ADDRESS_NUMBER-1:0] in_a_r=0; reg [5:0] in_ba_r=0; reg [1:0] in_we_r=2'h3, in_ras_r=2'h3, in_cas_r=2'h3, in_cke_r=2'h3, in_odt_r=2'h0; reg [1:0] in_tri_r=2'h0; // or tri-state on reset? reg [7:0] dly_data_r=0; reg set_r=0; reg [7:0] ld_dly_cmd=8'b0; reg [ADDRESS_NUMBER-1:0] ld_dly_addr=0; wire [ADDRESS_NUMBER-1:0] decode_addr; wire [7:0] decode_sel={ (dly_addr[2:0]==7)?1'b1:1'b0, (dly_addr[2:0]==6)?1'b1:1'b0, (dly_addr[2:0]==5)?1'b1:1'b0, (dly_addr[2:0]==4)?1'b1:1'b0, (dly_addr[2:0]==3)?1'b1:1'b0, (dly_addr[2:0]==2)?1'b1:1'b0, (dly_addr[2:0]==1)?1'b1:1'b0, (dly_addr[2:0]==0)?1'b1:1'b0}; always @ (posedge clk_div or posedge rst) begin if (rst) begin in_a_r <= 0; in_ba_r <= 6'b0; in_we_r <= 2'h3; in_ras_r <= 2'h3; in_cas_r <= 2'h3; in_cke_r <= 2'h3; in_odt_r <= 2'h0; in_tri_r <= 2'h0; // or tri-state on reset? dly_data_r<=8'b0;set_r<=1'b0; ld_dly_cmd <= 8'b0; ld_dly_addr <= 0; end else begin in_a_r <= in_a; in_ba_r <= in_ba; in_we_r <= in_we; in_ras_r <= in_ras; in_cas_r <= in_cas; in_cke_r <= in_cke; in_odt_r <= in_odt; in_tri_r <= in_tri; dly_data_r<=dly_data;set_r<=set; ld_dly_cmd <= {8 { dly_addr[4] & dly_addr[3] & ld_delay}} & decode_sel[7:0]; ld_dly_addr <= {(ADDRESS_NUMBER-1) {ld_delay}} & decode_addr; end end // All addresses generate genvar i; for (i=0; i<ADDRESS_NUMBER; i=i+1) begin: addr_block assign decode_addr[i]=(ld_dly_addr[4:0] == i)?1'b1:1'b0; cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_addr_i ( .dq(ddr3_a), // I/O pad (appears on the output 1/2 clk_div earlier, than DDR data) .clk(clk), // free-running system clock, same frequency as iclk (shared for R/W) .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 .tin(in_tri_r[1:0]), // tristate for data out (sent out earlier than data!) .set_delay(set_r), // clk_div synchronous load odelay value from dly_data .ld_delay(ld_dly_addr[i]) // clk_div synchronous set odealy value from loaded ); end endgenerate // Bank addresses // ba0 cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_ba0_i ( .dq(ddr3_ba[0]), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_ba_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[0])); // ba1 cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_ba1_i ( .dq(ddr3_ba[1]), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_ba_r[3:2]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[1])); // ba2 cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_ba2_i ( .dq(ddr3_ba[2]), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_ba_r[5:4]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[2])); // we cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_we_i ( .dq(ddr3_we), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_we_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[3])); // ras cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_ras_i ( .dq(ddr3_ras), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_ras_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[4])); // cas cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_cas_i( .dq(ddr3_cas), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_cas_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[5])); // cke cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_cke_i ( .dq(ddr3_cke), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_cke_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[6])); // odt cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_odt_i ( .dq(ddr3_odt), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_odt_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[7])); endmodule phy/cmda_single.v +13 −58 Original line number Diff line number Diff line Loading @@ -22,36 +22,24 @@ module cmda_single #( parameter IODELAY_GRP ="IODELAY_MEMORY", parameter IBUF_LOW_PWR ="TRUE", parameter IOSTANDARD = "SSTL15", parameter SLEW = "SLOW", parameter real REFCLK_FREQUENCY = 300.0, parameter HIGH_PERFORMANCE_MODE = "FALSE" )( inout dq, // I/O pad input iclk, // source-synchronous clock (BUFR from DQS) output dq, // I/O pad (appears on the output 1/2 clk_div earlier, than DDR data) 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 inv_clk_div, // invert clk_div for R channel (clk_div is shared between R and W) input rst, input dci_disable, // disable DCI termination during writes and idle input [7:0] dly_data, // delay value (3 LSB - fine delay) input [3:0] din, // parallel data to be sent out input [3:0] tin, // tristate for data out (sent out earlier than data!) output [3:0] dout, // parallel data received from DDR3 memory input set_odelay, // clk_div synchronous load odelay value from dly_data input ld_odelay, // clk_div synchronous set odealy value from loaded input set_idelay, // clk_div synchronous load idelay value from dly_data input ld_idelay // clk_div synchronous set idealy value from loaded input [1:0] din, // parallel data to be sent out input [1:0] tin, // tristate for data out (sent out earlier than data!) input set_delay, // clk_div synchronous load odelay value from dly_data input ld_delay // clk_div synchronous set odealy value from loaded ); wire d_ser; wire dq_tri; wire dq_data_dly; wire dq_dly; // keep IOBUF_DCIEN.O to user as output only (UDM/LDM), so the rest of tyhe read channel will be optimized out, but I/O will stay the same (* keep = "true" *) wire dq_di; oserdes_mem#( .MODE_DDR("FALSE") Loading @@ -59,8 +47,8 @@ oserdes_mem#( .clk(clk), // serial output clock .clk_div(clk_div), // oclk divided by 2, front aligned .rst(rst), // reset .din(din[3:0]), // parallel data in .tin(tin[3:0]), // parallel tri-state in .din(din[1:0]), // parallel data in .tin(tin[1:0]), // parallel tri-state in .dout_dly(d_ser), // data out to be connected to odelay input .dout_iob(), // data out to be connected directly to the output buffer .tout_dly(), // tristate out to be connected to odelay input Loading @@ -74,53 +62,20 @@ odelay_fine_pipe # ( ) dqs_out_dly_i( .clk(clk_div), .rst(rst), .set(set_odelay), .ld(ld_odelay), .set(set_delay), .ld(ld_delay), .delay(dly_data[7:0]), .data_in(d_ser), .data_out(dq_data_dly) ); IOBUF_DCIEN #( .IBUF_LOW_PWR(IBUF_LOW_PWR), // OBUFT #( .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .USE_IBUFDISABLE("FALSE") .SLEW(SLEW) ) iobufs_dqs_i ( .O(dq_di), .IO(dq), .DCITERMDISABLE(dci_disable), .IBUFDISABLE(1'b0), .I(dq_data_dly), //dqs_data), .O(dq), .I(dq_data_dly), .T(dq_tri)); idelay_fine_pipe # ( .IODELAY_GRP(IODELAY_GRP), .DELAY_VALUE(0), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) dqs_in_dly_i( .clk(clk_div), .rst(rst), .set(set_idelay), .ld(ld_idelay), .delay(dly_data[7:0]), .data_in(dq_di), .data_out(dq_dly) ); iserdes_mem #( .DYN_CLKDIV_INV_EN("FALSE") ) iserdes_mem_i ( .iclk(iclk), // source-synchronous clock .oclk(clk), // system clock, phase should allow iclk-to-oclk jitter with setup/hold margin .oclk_div(clk_div), // oclk divided by 2, front aligned .inv_clk_div(inv_clk_div), // invert oclk_div (this clock is shared between iserdes and oserdes. Works only in MEMORY_DDR3 mode? .rst(rst), // reset .d_direct(1'b0), // direct input from IOB, normally not used, controlled by IOBDELAY parameter (set to "NONE") .ddly(dq_dly), // serial input from idelay .dout(dout[3:0]) // parallel data out ); endmodule Loading
phy/byte_lane.v +3 −3 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ * Module: byte_lane * Date:2014-04-26 * Author: Andrey Filippov * Description: DDR3 byte lane, ingluding DQS I/O, 8xDQ I/O and DM output * Description: DDR3 byte lane, including DQS I/O, 8xDQ I/O and DM output * * Copyright (c) 2014 Elphel, Inc. * byte_lane.v is free software; you can redistribute it and/or modify Loading Loading @@ -44,7 +44,7 @@ module byte_lane #( input [3:0] tin_dq, // tristate for data out (sent out earlier than data!) and dm input [3:0] din_dqs, // parallel data to be sent out over DQS input [3:0] tin_dqs, // tristate for DQS out (sent out earlier than data!) output [31:0] dout, // parallel data received from DDR3 memory, 4 bits per DG I/O output [31:0] dout, // parallel data received from DDR3 memory, 4 bits per DQ I/O 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) Loading Loading @@ -91,7 +91,7 @@ end generate genvar i; for (i=0; i<7; i=i+1) begin: dq_block for (i=0; i < 8; i=i+1) begin: dq_block dq_single #( .IODELAY_GRP(IODELAY_GRP), .IBUF_LOW_PWR(IBUF_LOW_PWR), Loading
phy/cmd_addr.v 0 → 100644 +259 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: cmd_addr * Date:2014-04-26 * Author: Andrey Filippov * Description: DDR3 command/address signals * * Copyright (c) 2014 Elphel, Inc. * cmd_addr.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. * * cmd_addr.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 cmd_addr #( parameter IODELAY_GRP = "IODELAY_MEMORY", parameter IOSTANDARD = "SSTL15", parameter SLEW = "SLOW", parameter real REFCLK_FREQUENCY = 300.0, parameter HIGH_PERFORMANCE_MODE = "FALSE", parameter ADDRESS_NUMBER= 15 )( 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 output ddr3_ras, // output RAS port output ddr3_cas, // output CAS port output ddr3_cke, // output Clock Enable port output ddr3_odt, // output ODT port 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 rst, // 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 [5:0] in_ba, // input bank address, 2 bits per signal (first, second) input [1:0] in_we, // input WE, 2 bits (first, second) input [1:0] in_ras, // input RAS, 2 bits (first, second) input [1:0] in_cas, // input CAS, 2 bits (first, second) input [1:0] in_cke, // input CKE, 2 bits (first, second) input [1:0] in_odt, // input ODT, 2 bits (first, second) input [1:0] 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 set // clk_div synchronous set all delays from previously loaded values ); reg [2*ADDRESS_NUMBER-1:0] in_a_r=0; reg [5:0] in_ba_r=0; reg [1:0] in_we_r=2'h3, in_ras_r=2'h3, in_cas_r=2'h3, in_cke_r=2'h3, in_odt_r=2'h0; reg [1:0] in_tri_r=2'h0; // or tri-state on reset? reg [7:0] dly_data_r=0; reg set_r=0; reg [7:0] ld_dly_cmd=8'b0; reg [ADDRESS_NUMBER-1:0] ld_dly_addr=0; wire [ADDRESS_NUMBER-1:0] decode_addr; wire [7:0] decode_sel={ (dly_addr[2:0]==7)?1'b1:1'b0, (dly_addr[2:0]==6)?1'b1:1'b0, (dly_addr[2:0]==5)?1'b1:1'b0, (dly_addr[2:0]==4)?1'b1:1'b0, (dly_addr[2:0]==3)?1'b1:1'b0, (dly_addr[2:0]==2)?1'b1:1'b0, (dly_addr[2:0]==1)?1'b1:1'b0, (dly_addr[2:0]==0)?1'b1:1'b0}; always @ (posedge clk_div or posedge rst) begin if (rst) begin in_a_r <= 0; in_ba_r <= 6'b0; in_we_r <= 2'h3; in_ras_r <= 2'h3; in_cas_r <= 2'h3; in_cke_r <= 2'h3; in_odt_r <= 2'h0; in_tri_r <= 2'h0; // or tri-state on reset? dly_data_r<=8'b0;set_r<=1'b0; ld_dly_cmd <= 8'b0; ld_dly_addr <= 0; end else begin in_a_r <= in_a; in_ba_r <= in_ba; in_we_r <= in_we; in_ras_r <= in_ras; in_cas_r <= in_cas; in_cke_r <= in_cke; in_odt_r <= in_odt; in_tri_r <= in_tri; dly_data_r<=dly_data;set_r<=set; ld_dly_cmd <= {8 { dly_addr[4] & dly_addr[3] & ld_delay}} & decode_sel[7:0]; ld_dly_addr <= {(ADDRESS_NUMBER-1) {ld_delay}} & decode_addr; end end // All addresses generate genvar i; for (i=0; i<ADDRESS_NUMBER; i=i+1) begin: addr_block assign decode_addr[i]=(ld_dly_addr[4:0] == i)?1'b1:1'b0; cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_addr_i ( .dq(ddr3_a), // I/O pad (appears on the output 1/2 clk_div earlier, than DDR data) .clk(clk), // free-running system clock, same frequency as iclk (shared for R/W) .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 .tin(in_tri_r[1:0]), // tristate for data out (sent out earlier than data!) .set_delay(set_r), // clk_div synchronous load odelay value from dly_data .ld_delay(ld_dly_addr[i]) // clk_div synchronous set odealy value from loaded ); end endgenerate // Bank addresses // ba0 cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_ba0_i ( .dq(ddr3_ba[0]), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_ba_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[0])); // ba1 cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_ba1_i ( .dq(ddr3_ba[1]), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_ba_r[3:2]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[1])); // ba2 cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_ba2_i ( .dq(ddr3_ba[2]), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_ba_r[5:4]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[2])); // we cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_we_i ( .dq(ddr3_we), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_we_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[3])); // ras cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_ras_i ( .dq(ddr3_ras), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_ras_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[4])); // cas cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_cas_i( .dq(ddr3_cas), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_cas_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[5])); // cke cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_cke_i ( .dq(ddr3_cke), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_cke_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[6])); // odt cmda_single #( .IODELAY_GRP(IODELAY_GRP), .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) cmda_odt_i ( .dq(ddr3_odt), .clk(clk), .clk_div(clk_div), .rst(rst), .dly_data(dly_data_r[7:0]), .din(in_odt_r[1:0]), .tin(in_tri_r[1:0]), .set_delay(set_r), .ld_delay(ld_dly_cmd[7])); endmodule
phy/cmda_single.v +13 −58 Original line number Diff line number Diff line Loading @@ -22,36 +22,24 @@ module cmda_single #( parameter IODELAY_GRP ="IODELAY_MEMORY", parameter IBUF_LOW_PWR ="TRUE", parameter IOSTANDARD = "SSTL15", parameter SLEW = "SLOW", parameter real REFCLK_FREQUENCY = 300.0, parameter HIGH_PERFORMANCE_MODE = "FALSE" )( inout dq, // I/O pad input iclk, // source-synchronous clock (BUFR from DQS) output dq, // I/O pad (appears on the output 1/2 clk_div earlier, than DDR data) 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 inv_clk_div, // invert clk_div for R channel (clk_div is shared between R and W) input rst, input dci_disable, // disable DCI termination during writes and idle input [7:0] dly_data, // delay value (3 LSB - fine delay) input [3:0] din, // parallel data to be sent out input [3:0] tin, // tristate for data out (sent out earlier than data!) output [3:0] dout, // parallel data received from DDR3 memory input set_odelay, // clk_div synchronous load odelay value from dly_data input ld_odelay, // clk_div synchronous set odealy value from loaded input set_idelay, // clk_div synchronous load idelay value from dly_data input ld_idelay // clk_div synchronous set idealy value from loaded input [1:0] din, // parallel data to be sent out input [1:0] tin, // tristate for data out (sent out earlier than data!) input set_delay, // clk_div synchronous load odelay value from dly_data input ld_delay // clk_div synchronous set odealy value from loaded ); wire d_ser; wire dq_tri; wire dq_data_dly; wire dq_dly; // keep IOBUF_DCIEN.O to user as output only (UDM/LDM), so the rest of tyhe read channel will be optimized out, but I/O will stay the same (* keep = "true" *) wire dq_di; oserdes_mem#( .MODE_DDR("FALSE") Loading @@ -59,8 +47,8 @@ oserdes_mem#( .clk(clk), // serial output clock .clk_div(clk_div), // oclk divided by 2, front aligned .rst(rst), // reset .din(din[3:0]), // parallel data in .tin(tin[3:0]), // parallel tri-state in .din(din[1:0]), // parallel data in .tin(tin[1:0]), // parallel tri-state in .dout_dly(d_ser), // data out to be connected to odelay input .dout_iob(), // data out to be connected directly to the output buffer .tout_dly(), // tristate out to be connected to odelay input Loading @@ -74,53 +62,20 @@ odelay_fine_pipe # ( ) dqs_out_dly_i( .clk(clk_div), .rst(rst), .set(set_odelay), .ld(ld_odelay), .set(set_delay), .ld(ld_delay), .delay(dly_data[7:0]), .data_in(d_ser), .data_out(dq_data_dly) ); IOBUF_DCIEN #( .IBUF_LOW_PWR(IBUF_LOW_PWR), // OBUFT #( .IOSTANDARD(IOSTANDARD), .SLEW(SLEW), .USE_IBUFDISABLE("FALSE") .SLEW(SLEW) ) iobufs_dqs_i ( .O(dq_di), .IO(dq), .DCITERMDISABLE(dci_disable), .IBUFDISABLE(1'b0), .I(dq_data_dly), //dqs_data), .O(dq), .I(dq_data_dly), .T(dq_tri)); idelay_fine_pipe # ( .IODELAY_GRP(IODELAY_GRP), .DELAY_VALUE(0), .REFCLK_FREQUENCY(REFCLK_FREQUENCY), .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE) ) dqs_in_dly_i( .clk(clk_div), .rst(rst), .set(set_idelay), .ld(ld_idelay), .delay(dly_data[7:0]), .data_in(dq_di), .data_out(dq_dly) ); iserdes_mem #( .DYN_CLKDIV_INV_EN("FALSE") ) iserdes_mem_i ( .iclk(iclk), // source-synchronous clock .oclk(clk), // system clock, phase should allow iclk-to-oclk jitter with setup/hold margin .oclk_div(clk_div), // oclk divided by 2, front aligned .inv_clk_div(inv_clk_div), // invert oclk_div (this clock is shared between iserdes and oserdes. Works only in MEMORY_DDR3 mode? .rst(rst), // reset .d_direct(1'b0), // direct input from IOB, normally not used, controlled by IOBDELAY parameter (set to "NONE") .ddly(dq_dly), // serial input from idelay .dout(dout[3:0]) // parallel data out ); endmodule