diff --git a/rtl/iddr.v b/rtl/iddr.v index 8651e095..53e3d583 100644 --- a/rtl/iddr.v +++ b/rtl/iddr.v @@ -33,19 +33,15 @@ THE SOFTWARE. */ module iddr # ( - // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", - // IODDR style ("IODDR", "IODDR2") - // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale - // Use IODDR2 for Spartan-6 - parameter IODDR_STYLE = "IODDR2", // Width of register in bits parameter WIDTH = 1, - parameter INSERT_BUFFERS = "FALSE" + parameter INSERT_BUFFERS = "FALSE", + // Can be count or time depending on delay type + parameter [8:0] DELAY_VALUE = 9'h19 ) ( input wire clk, - + // Data input input wire [WIDTH-1:0] d, output wire [WIDTH-1:0] q1, @@ -66,6 +62,8 @@ Provides a consistent input DDR flip flop across multiple FPGA families */ wire [WIDTH-1:0] d_int; +wire [WIDTH-1:0] delayed_data_int; + genvar n; generate @@ -81,71 +79,38 @@ end else begin assign d_int = d; end -if (TARGET == "XILINX") begin - for (n = 0; n < WIDTH; n = n + 1) begin : iddr - if (IODDR_STYLE == "IODDR") begin - IDDR #( - .DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), - .SRTYPE("ASYNC") - ) - iddr_inst ( - .Q1(q1[n]), - .Q2(q2[n]), - .C(clk), - .CE(1'b1), - .D(d_int[n]), - .R(1'b0), - .S(1'b0) - ); - end else if (IODDR_STYLE == "IODDR2") begin - wire q1_int; - reg q1_delay; - - IDDR2 #( - .DDR_ALIGNMENT("C0") - ) - iddr_inst ( - .Q0(q1_int), - .Q1(q2[n]), - .C0(clk), - .C1(~clk), - .CE(1'b1), - .D(d_int[n]), - .R(1'b0), - .S(1'b0) - ); - - always @(posedge clk) begin - q1_delay <= q1_int; - end - - assign q1[n] = q1_delay; - end - end -end else if (TARGET == "ALTERA") begin - wire [WIDTH-1:0] q1_int; - reg [WIDTH-1:0] q1_delay; - - altddio_in #( - .WIDTH(WIDTH), - .POWER_UP_HIGH("OFF") +for (n = 0; n < WIDTH; n = n + 1) begin : iddr + // Use IDELAYE3 for Ultrascale and Ultrascale+ devices to adjust delay between clock and data + // found delay count value by sweeping and checking the output + IDELAYE3 #( + .CASCADE("NONE"), + .DELAY_FORMAT("COUNT"), // Units of the DELAY_VALUE (COUNT, TIME) + .DELAY_SRC("IDATAIN"), + .DELAY_TYPE("FIXED"), + .DELAY_VALUE(9'h19), + .IS_CLK_INVERTED(1'b0), + .IS_RST_INVERTED(1'b0), + .REFCLK_FREQUENCY(300.0), + .SIM_DEVICE("ULTRASCALE_PLUS"), + .UPDATE_MODE("ASYNC") ) - altddio_in_inst ( - .aset(1'b0), - .datain(d_int), - .inclocken(1'b1), - .inclock(clk), - .aclr(1'b0), - .dataout_h(q1_int), - .dataout_l(q2) + IDELAYE3_inst ( + .CASC_OUT(), + .CNTVALUEOUT(), + .DATAOUT(delayed_data_int[n]), + .CASC_IN(0), + .CASC_RETURN(0), + .CE(0), + .CLK(clk), + .CNTVALUEIN(0), + .DATAIN(0), + .EN_VTC(0), + .IDATAIN(d_int[n]), + .INC(0), + .LOAD(0), + .RST(0) ); - - always @(posedge clk) begin - q1_delay <= q1_int; - end - - assign q1 = q1_delay; -end else begin +end reg [WIDTH-1:0] d_reg_1 = {WIDTH{1'b0}}; reg [WIDTH-1:0] d_reg_2 = {WIDTH{1'b0}}; @@ -153,11 +118,11 @@ end else begin reg [WIDTH-1:0] q_reg_2 = {WIDTH{1'b0}}; always @(posedge clk) begin - d_reg_1 <= d_int; + d_reg_1 <= delayed_data_int; end always @(negedge clk) begin - d_reg_2 <= d_int; + d_reg_2 <= delayed_data_int; end always @(posedge clk) begin @@ -167,7 +132,6 @@ end else begin assign q1 = q_reg_1; assign q2 = q_reg_2; -end endgenerate diff --git a/rtl/rgmii_phy_if.v b/rtl/rgmii_phy_if.v index 9275f2c8..37d69f10 100644 --- a/rtl/rgmii_phy_if.v +++ b/rtl/rgmii_phy_if.v @@ -34,18 +34,20 @@ THE SOFTWARE. module rgmii_phy_if # ( // target ("SIM", "GENERIC", "XILINX", "ALTERA") - parameter TARGET = "GENERIC", + parameter TARGET = "XILINX", // IODDR style ("IODDR", "IODDR2") // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale // Use IODDR2 for Spartan-6 - parameter IODDR_STYLE = "IODDR2", + parameter IODDR_STYLE = "IODDR", // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") // Use BUFR for Virtex-6, 7-series // Use BUFG for Virtex-5, Spartan-6, Ultrascale - parameter CLOCK_INPUT_STYLE = "BUFG", + parameter CLOCK_INPUT_STYLE = "BUFIO", // Use 90 degree clock for RGMII transmit ("TRUE", "FALSE") parameter USE_CLK90 = "TRUE", - parameter INSERT_BUFFERS = "TRUE" + parameter INSERT_BUFFERS = "TRUE", + // Delay value for input data in count or time units + parameter [8:0] DELAY_VALUE = 9'h19 ) ( // Reset, synchronous to gmii_gtx_clk @@ -93,7 +95,6 @@ module rgmii_phy_if # wire clk; // receive - wire rgmii_rx_ctl_1; wire rgmii_rx_ctl_2; @@ -101,9 +102,9 @@ ssio_ddr_in # ( .TARGET(TARGET), .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE), - .IODDR_STYLE(IODDR_STYLE), .WIDTH(5), - .INSERT_BUFFERS(INSERT_BUFFERS) + .INSERT_BUFFERS(INSERT_BUFFERS), + .DELAY_VALUE (DELAY_VALUE) ) rx_ssio_ddr_inst ( .input_clk(rgmii_rxc), diff --git a/rtl/ssio_ddr_in.v b/rtl/ssio_ddr_in.v index ea6274e1..1a701ff2 100644 --- a/rtl/ssio_ddr_in.v +++ b/rtl/ssio_ddr_in.v @@ -35,17 +35,14 @@ module ssio_ddr_in # ( // target ("SIM", "GENERIC", "XILINX", "ALTERA") parameter TARGET = "GENERIC", - // IODDR style ("IODDR", "IODDR2") - // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale - // Use IODDR2 for Spartan-6 - parameter IODDR_STYLE = "IODDR2", // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2") // Use BUFR for Virtex-6, 7-series // Use BUFG for Virtex-5, Spartan-6, Ultrascale parameter CLOCK_INPUT_STYLE = "BUFG", // Width of register in bits parameter WIDTH = 1, - parameter INSERT_BUFFERS = "FALSE" + parameter INSERT_BUFFERS = "FALSE", + parameter [8:0] DELAY_VALUE = 9'h19 ) ( input wire input_clk, @@ -145,11 +142,12 @@ end endgenerate + + iddr #( - .TARGET(TARGET), - .IODDR_STYLE(IODDR_STYLE), .WIDTH(WIDTH), - .INSERT_BUFFERS(INSERT_BUFFERS) + .INSERT_BUFFERS(INSERT_BUFFERS), + .DELAY_VALUE(DELAY_VALUE) ) data_iddr_inst ( .clk(clk_io),