Author Topic: DDR3 initialization sequence issue  (Read 65271 times)

0 Members and 1 Guest are viewing this topic.

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3150
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #450 on: August 28, 2021, 11:05:01 pm »
Quote
OLOGIC and ILOGIC are parts of the IO object and they must be clocked the same (as the docs say)

Could you point to the exact page of the Xilinx doc that mentions the above ?

Somewhere in the middle of the thread you have posted a big table which lists all the compatible clock modes, from which it was clear that ILOGIC and OLOGIC are clocked with the same clock(s). Since then, along the thread, this issue has been discussed several times.
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #451 on: August 29, 2021, 01:29:12 am »
ok, found it.

So, I presume that the routing error is actually due to DDR_ALIGNMENT needs to be modified for both IDDR and ODDR , instead of just ODDR which is what I did.

However, when I change for both IDDR and ODDR, I have mapping error though.  The error content sentences seem contradictory to one another.

Code: [Select]
ERROR:Pack:2403 - Due to a hardware restriction when an input dual-data register
   has the same clock signal on its clock pins the clock pins needed to have an
   opposite inversion. Please correct inversions on register
   ddr3_control/dq_io[2].IDDR2_dq_r.
ERROR:Pack:2403 - Due to a hardware restriction when an input dual-data register
   has the same clock signal on its clock pins the clock pins needed to have an
   opposite inversion. Please correct inversions on register
   ddr3_control/dq_io[3].IDDR2_dq_r.
ERROR:Pack:2403 - Due to a hardware restriction when an input dual-data register
   has the same clock signal on its clock pins the clock pins needed to have an
   opposite inversion. Please correct inversions on register
   ddr3_control/dq_io[4].IDDR2_dq_r.
ERROR:Pack:2403 - Due to a hardware restriction when an input dual-data register
   has the same clock signal on its clock pins the clock pins needed to have an
   opposite inversion. Please correct inversions on register
   ddr3_control/dq_io[5].IDDR2_dq_r.
ERROR:Pack:2403 - Due to a hardware restriction when an input dual-data register
   has the same clock signal on its clock pins the clock pins needed to have an
   opposite inversion. Please correct inversions on register
   ddr3_control/dq_io[6].IDDR2_dq_r.
ERROR:Pack:2403 - Due to a hardware restriction when an input dual-data register
   has the same clock signal on its clock pins the clock pins needed to have an
   opposite inversion. Please correct inversions on register
   ddr3_control/dq_io[7].IDDR2_dq_r.
ERROR:Pack:2529 - The dual data rate register "ddr3_control/dq_io[2].IDDR2_dq_r"
   failed to join an ILOGIC component as required.
ERROR:Pack:2529 - The dual data rate register "ddr3_control/dq_io[7].IDDR2_dq_r"
   failed to join an ILOGIC component as required.
ERROR:Pack:2529 - The dual data rate register "ddr3_control/dq_io[5].IDDR2_dq_r"
   failed to join an ILOGIC component as required.
ERROR:Pack:2529 - The dual data rate register "ddr3_control/dq_io[3].IDDR2_dq_r"
   failed to join an ILOGIC component as required.
ERROR:Pack:2529 - The dual data rate register "ddr3_control/dq_io[6].IDDR2_dq_r"
   failed to join an ILOGIC component as required.
ERROR:Pack:2529 - The dual data rate register "ddr3_control/dq_io[4].IDDR2_dq_r"
   failed to join an ILOGIC component as required.

« Last Edit: August 29, 2021, 01:47:25 am by promach »
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3150
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #452 on: August 29, 2021, 02:23:00 am »
Code: [Select]
ERROR:Pack:2403 - Due to a hardware restriction when an input dual-data register
   has the same clock signal on its clock pins the clock pins needed to have an
   opposite inversion. Please correct inversions on register
   ddr3_control/dq_io[2].IDDR2_dq_r.

I guess it says that C1 must be an inversion of C0. [/code]
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #453 on: August 29, 2021, 02:27:08 am »
Thanks for the advice and I got past the mapping error, but I am back to the routing error again.

 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #454 on: August 29, 2021, 03:02:40 am »
I did some tweaking here and there, and I got past the routing error.

Code: [Select]
diff --git a/ddr3_memory_controller.v b/ddr3_memory_controller.v
index b30e493..8be1957 100644
--- a/ddr3_memory_controller.v
+++ b/ddr3_memory_controller.v
@@ -744,14 +744,14 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  // see https://forums.xilinx.com/t5/Other-FPGA-Architecture/Place-1198-Error-Route-cause-and-possible-solution/m-p/408489/highlight/true#M34528
 
  ODDR2 #(
- .DDR_ALIGNMENT("NONE"),  // Sets output alignment to "NONE", "C0" or "C1"
+ .DDR_ALIGNMENT("C0"),  // Sets output alignment to "NONE", "C0" or "C1"
  .INIT(1'b0),  // Sets initial state of the Q output to 1'b0 or 1'b1
- .SRTYPE("SYNC")  // Specifies "SYNC" or "ASYNC" set/reset
+ .SRTYPE("ASYNC")  // Specifies "SYNC" or "ASYNC" set/reset
  )
  ODDR2_ck_out(
  .Q(ck_out),  // 1-bit DDR output data
  .C0(ck),  // 1-bit clock input
- .C1(ck_180),  // 1-bit clock input
+ .C1(ck),  // 1-bit clock input
  .CE(1'b1),  // 1-bit clock enable input
  .D0(1'b1),    // 1-bit DDR data input (associated with C0)
  .D1(1'b0),    // 1-bit DDR data input (associated with C1)
@@ -760,14 +760,14 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  );
 
  ODDR2 #(
- .DDR_ALIGNMENT("NONE"),  // Sets output alignment to "NONE", "C0" or "C1"
+ .DDR_ALIGNMENT("C0"),  // Sets output alignment to "NONE", "C0" or "C1"
  .INIT(1'b0),  // Sets initial state of the Q output to 1'b0 or 1'b1
- .SRTYPE("SYNC")  // Specifies "SYNC" or "ASYNC" set/reset
+ .SRTYPE("ASYNC")  // Specifies "SYNC" or "ASYNC" set/reset
  )
  ODDR2_ck_180_out(
  .Q(ck_180_out),  // 1-bit DDR output data
  .C0(ck_180),  // 1-bit clock input
- .C1(ck),  // 1-bit clock input
+ .C1(ck_180),  // 1-bit clock input
  .CE(1'b1),  // 1-bit clock enable input
  .D0(1'b1),    // 1-bit DDR data input (associated with C0)
  .D1(1'b0),    // 1-bit DDR data input (associated with C1)
@@ -1049,7 +1049,7 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  // will implement dynamic (real-time) phase calibration as project progresses
  wire idelay_cal_dqs_r = &iodelay_startup_counter;  // Wait for IODELAY to be available
 
-
+/*
  IODELAY2 #(
  .DATA_RATE      ("DDR"), // <SDR>, DDR
  .IDELAY_VALUE  (0), // {0 ... 255}
@@ -1078,7 +1078,7 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  .RST      (idelay_is_busy_previously & (~idelay_is_busy)), // Reset delay line
  .BUSY      (idelay_is_busy) // output signal indicating sync circuit has finished / calibration has finished
  );
-
+*/
 
  // RAM -> IOBUF (for inout) -> IDELAY (DQS Centering) -> IDDR2 (input DDR buffer) -> ISERDES
  // OSERDES -> ODDR2 (output DDR buffer) -> ODELAY (DQS Centering) -> IOBUF (for inout) -> RAM
@@ -1093,7 +1093,7 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  wire [DQ_BITWIDTH-1:0] dq_w_oserdes_0;  // associated with dqs_w
  wire [DQ_BITWIDTH-1:0] dq_w_oserdes_1;  // associated with dq_n_w
 
- always @(posedge ck_180)     dq_w_d0 <= dq_w_oserdes_0;  // for C0, D0 of ODDR2 primitive
+ always @(posedge ck)     dq_w_d0 <= dq_w_oserdes_0;  // for C0, D0 of ODDR2 primitive
  always @(posedge ck) dq_w_d1 <= dq_w_oserdes_1;  // for C1, D1 of ODDR2 primitive
 
 
@@ -1172,7 +1172,7 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  dq_iserdes_1
  (
  // fast clock domain
- .high_speed_clock(ck_270),
+ .high_speed_clock(ck_90),
  .data_in(dq_r_q1),
 
  // slow clock domain
@@ -1241,7 +1241,7 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  .data_in(data_in_oserdes_0),
 
  // fast clock domain
- .high_speed_clock(ck_270),
+ .high_speed_clock(ck_90),
  .data_out(dq_w_oserdes_0)
  );
 
@@ -1609,9 +1609,9 @@ wire data_write_is_ongoing = ((wait_count > TIME_WL-TIME_TWPRE) &&
  // Xilinx HDL Libraries Guide, version 14.7
 
  ODDR2 #(
- .DDR_ALIGNMENT("NONE"),  // Sets output alignment to "NONE", "C0" or "C1"
+ .DDR_ALIGNMENT("C0"),  // Sets output alignment to "NONE", "C0" or "C1"
  .INIT(1'b0),  // Sets initial state of the Q output to 1'b0 or 1'b1
- .SRTYPE("SYNC")  // Specifies "SYNC" or "ASYNC" set/reset
+ .SRTYPE("ASYNC")  // Specifies "SYNC" or "ASYNC" set/reset
  )
  ODDR2_dq_iobuf_en(
  .Q(dq_iobuf_enable[dq_index]),  // 1-bit DDR output data
@@ -1634,10 +1634,10 @@ wire data_write_is_ongoing = ((wait_count > TIME_WL-TIME_TWPRE) &&
  // Xilinx HDL Libraries Guide, version 14.7
 
  IDDR2 #(
- .DDR_ALIGNMENT("NONE"),  // Sets output alignment to "NONE", "C0" or "C1"
+ .DDR_ALIGNMENT("C0"),  // Sets output alignment to "NONE", "C0" or "C1"
  .INIT_Q0(1'b0),  // Sets initial state of the Q0 output to 1'b0 or 1'b1
  .INIT_Q1(1'b0),  // Sets initial state of the Q1 output to 1'b0 or 1'b1
- .SRTYPE("SYNC")  // Specifies "SYNC" or "ASYNC" set/reset
+ .SRTYPE("ASYNC")  // Specifies "SYNC" or "ASYNC" set/reset
  )
  IDDR2_dq_r(
  .Q0(dq_r_q0[dq_index]),  // 1-bit output captured with C0 clock
@@ -1657,9 +1657,9 @@ wire data_write_is_ongoing = ((wait_count > TIME_WL-TIME_TWPRE) &&
  // Xilinx HDL Libraries Guide, version 14.7
 
  ODDR2 #(
- .DDR_ALIGNMENT("NONE"),  // Sets output alignment to "NONE", "C0" or "C1"
+ .DDR_ALIGNMENT("C0"),  // Sets output alignment to "NONE", "C0" or "C1"
  .INIT(1'b0),  // Sets initial state of the Q output to 1'b0 or 1'b1
- .SRTYPE("SYNC")  // Specifies "SYNC" or "ASYNC" set/reset
+ .SRTYPE("ASYNC")  // Specifies "SYNC" or "ASYNC" set/reset
  )
  ODDR2_dq_w(
  .Q(dq_w[dq_index]),  // 1-bit DDR output data
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #455 on: August 29, 2021, 06:49:18 am »
Now, I am solving setup timing violation for dq_r_q0

I do not see anything wrong with deserializer module that could contribute to setup timing issue.

Any advice ?

 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3150
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #456 on: August 29, 2021, 01:08:56 pm »
Now, I am solving setup timing violation for dq_r_q0

I do not see anything wrong with deserializer module that could contribute to setup timing issue.

Any advice ?

When you pass a signal from a clock to a different clock which only differs in phase, the phase difference is very important.

It is relatively easy to do if the phase difference is 270 degrees.

It is hard (if at all possible) at high frequencies if the phase difference is 180 degrees.

It is impossible at 350 MHz when the phase difference is 90 degrees. You can aim for the next cycle (that is -270 degree difference), but most likely it will be impossible to meet hold violations.

The solution is to use IDELAY to shift DQ and align it with a regular clock.

You need to shift DQ anyway because the phase relationship between DQ and CK depends on the round trip delay:

CK->DDR3 chip->DQ->IDDR

and therefore is unpredictable. So, your controller should be ready for any phase difference.
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #457 on: August 29, 2021, 04:13:18 pm »
Quote
The solution is to use IDELAY to shift DQ and align it with a regular clock.

I am using @BrianHG method of PLL dynamic phase shift approach.

With the following modification, I had mapping error.
I checked inside this Xilinx forum post, I do not see how site A10 is related to BUFGMUX_X2Y12

Code: [Select]
diff --git a/ddr3_memory_controller.v b/ddr3_memory_controller.v
index b663904..a9f0e22 100644
--- a/ddr3_memory_controller.v
+++ b/ddr3_memory_controller.v
@@ -684,6 +684,7 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
 
  localparam PLL_STATUS_BITWIDTH = 3;
 
+ wire ck_dynamic, ck_dynamic_180;
  wire locked_dynamic;
  wire [PLL_STATUS_BITWIDTH-1:0] pll_read_status;
  wire input_clk_stopped;
@@ -695,7 +696,8 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  .clk(clk),  // IN 50MHz
 
  // Clock out ports
- .ck_dynamic(ck_dynamic),  // OUT 400MHz, 0 phase shift
+ .ck_dynamic(ck_dynamic),  // OUT 350MHz, 0 phase shift
+ .ck_dynamic_180(ck_dynamic_180),  // OUT 350MHz, 180 phase shift
 
  // Dynamic phase shift ports
  .psclk(udqs_r),  // IN
@@ -1161,7 +1163,7 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  dq_iserdes_0
  (
  // fast clock domain
- .high_speed_clock(ck_90),
+ .high_speed_clock(ck_dynamic),
  .data_in(dq_r_q0),
 
  // slow clock domain
@@ -1172,7 +1174,7 @@ reg MPR_ENABLE, MPR_Read_had_finished;  // for use within MR3 finite state machi
  dq_iserdes_1
  (
  // fast clock domain
- .high_speed_clock(ck_90),
+ .high_speed_clock(ck_dynamic),
  .data_in(dq_r_q1),
 
  // slow clock domain
@@ -1647,8 +1649,8 @@ wire data_write_is_ongoing = ((wait_count > TIME_WL-TIME_TWPRE) &&
  IDDR2_dq_r(
  .Q0(dq_r_q0[dq_index]),  // 1-bit output captured with C0 clock
  .Q1(dq_r_q1[dq_index]),  // 1-bit output captured with C1 clock
- .C0(ck),  // 1-bit clock input
- .C1(ck_180),  // 1-bit clock input
+ .C0(ck_dynamic),  // 1-bit clock input
+ .C1(ck_dynamic_180),  // 1-bit clock input
  .CE(1'b1),  // 1-bit clock enable input
  .D(dq_r[dq_index]),    // 1-bit DDR data input
  .R(reset),    // 1-bit reset input

Code: [Select]
ERROR:Place:1108 - A clock IOB / BUFGMUX clock component pair have been found
   that are not placed at an optimal clock IOB / BUFGMUX site pair. The clock
   IOB component <clk> is placed at site <A10>. The corresponding BUFG component
   <ddr3_control/pll_read/clkin1_buf> is placed at site <BUFGMUX_X2Y12>. There
   is only a select set of IOBs that can use the fast path to the Clocker
   buffer, and they are not being used. You may want to analyze why this problem
   exists and correct it. If this sub optimal condition is acceptable for this
   design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .ucf file to
   demote this message to a WARNING and allow your design to continue. However,
   the use of this override is highly discouraged as it may lead to very poor
   timing results. It is recommended that this error condition be corrected in
   the design. A list of all the COMP.PINs used in this clock placement rule is
   listed below. These examples can be used directly in the .ucf file to
   override this clock rule.
   < NET "clk" CLOCK_DEDICATED_ROUTE = FALSE; >

« Last Edit: August 29, 2021, 04:22:34 pm by promach »
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3150
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #458 on: August 29, 2021, 06:45:56 pm »
I am using @BrianHG method of PLL dynamic phase shift approach.

Input and output must be clocked by the same clock. On writes, DQS is aligned to CK, so DQS must be clocked by CK. On reads, DQS may have any phase relationship with CK, so it cannot be the same clock as CK. The only way you can use BrianHG's method is if you dynamically re-align the clocks in-between reads and writes (or if you switch the clock dynamically). In this case, you will have a read clock domain and a write clock domain which should be treated as asynchronous - meaning you cannot use STA for transitions between these domains. Instead, you should use some sort of CDC solution.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7807
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #459 on: August 29, 2021, 09:39:26 pm »
According to this illustration here: https://www.eevblog.com/forum/fpga/ddr3-initialization-sequence-issue/msg3612509/#msg3612509

I think the issue may be with the 'Clock Doubler' module.

Shows you can have a different inclock and outclock, but you probably need to use the 'DDR Two BUFIO2s'.  There may be a restriction on which 2 sets of clocks you are allowed to use at the same time from the PLL.  Those 2 just become your priority when setting up your pll.


« Last Edit: August 29, 2021, 09:41:14 pm by BrianHG »
 
The following users thanked this post: promach

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3150
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #460 on: August 30, 2021, 02:37:41 am »
'DDR Two BUFIO2s'.

One BUFIO2s is 180 degrees shifted from the other. Hence you need two BUFIOs (or two BUFG, or one BUFG which it'll make into a pair internally). If you want DDR on both input and output, this is "... Only possible when the two BUFGs are common for both input and output", or "...Only possible when the two BUFIO2s are common for both input and output". Thus, the same pair feeds both input and output.
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #461 on: August 30, 2021, 03:03:14 am »
What do you exactly mean by Only possible when the two BUFIO2s are common for both input and output ?
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3150
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #462 on: August 30, 2021, 04:10:26 am »
What do you exactly mean by Only possible when the two BUFIO2s are common for both input and output ?

This is a citation from the Xilinx table.
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #463 on: August 30, 2021, 04:20:49 am »
Quote
Shows you can have a different inclock and outclock, but you probably need to use the 'DDR Two BUFIO2s'.

@BrianHG Does this mean for DQ (or DQS) double-data-rate IO signal, I could not use PLL dynamic phase shift approach ?
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #464 on: August 30, 2021, 01:33:42 pm »
Since BUFIO2 itself already had USE_DOUBLER=True attribute , then why still need "Clock Doubler" module ?

By the way, I do not quite understand how my current issue is related to the need of using two BUFIO2

 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3150
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #465 on: August 30, 2021, 04:48:12 pm »
Since BUFIO2 itself already had USE_DOUBLER=True attribute ,

If you use DDR, the ISERDES/OSERDES clock will have double frequency compared to SDR. That's all there is to it. Read the docs:

Quote
USE_DOUBLER - Used for ISERDES2/OSERDES2 with DATA_RATE = DDR. When set to TRUE, doubles the DIVCLK and SERDESSTROBE frequencies. FDIVCLK = (2 * FIN) / DIVIDE

DIVIDE - Sets the DIVCLK and SERDESSTROBE divider divide-by values.
  FDIVCLK = FIN / DIVIDE  <USE_DOUBLER = FALSE>
  FDIVCLK = (2 * FIN) / DIVIDE  <USE_DOUBLER = TRUE>

If you use IDDR/ODDR in place of ISERDES/OSERDES, DATA_RATE is always DDR (implied), so you always set USE_DOUBLER in BUFIO, so that the clock going to the fabric has the same frequency as the clock going to IDDR/ODDR

If you use BUFG, the BUFG itself can clock the fabric, so you don't need a special fabric clock as you do in case of BUFIO.
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #466 on: August 30, 2021, 04:55:34 pm »
Quote
If you use BUFG, the BUFG itself can clock the fabric, so you don't need a special fabric clock as you do in case of BUFIO.

I am using BUFG , so I suppose I do not need to worry about BUFIO in this case ?
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3150
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #467 on: August 30, 2021, 05:53:58 pm »
Quote
If you use BUFG, the BUFG itself can clock the fabric, so you don't need a special fabric clock as you do in case of BUFIO.

I am using BUFG , so I suppose I do not need to worry about BUFIO in this case ?

If you don't use BUFIO then you certainly don't need to worry about it. However, BUFIO can run much faster than BUFG.
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #468 on: August 31, 2021, 01:44:44 am »
Quote
BUFIO can run much faster than BUFG.

What do you exactly mean by faster ?

By the way, how to approach and solve the mapping error for BUFG ?

 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #469 on: August 31, 2021, 02:54:32 am »
Quote
Shows you can have a different inclock and outclock, but you probably need to use the 'DDR Two BUFIO2s'.  There may be a restriction on which 2 sets of clocks you are allowed to use at the same time from the PLL.  Those 2 just become your priority when setting up your pll.

I have solved the mapping error for BUFG by removing BUFG from the input clk for the pll_tuneable IP.

However, I have the following routing error which is related to the need of using 'DDR Two BUFIO2s'
@BrianHG could you advise ?

Note: The routing error arises from the C1 pins of the IDDR2_dq_r and ODDR2_dq_w

Code: [Select]
ERROR:Route:472 -
   This design is unrouteable.
   To evaluate the problem please use fpga_editor.
Routing Conflict 1:
Net:ddr3_control/ck_dynamic_180 on pin CLK1 on location ILOGIC_X0Y22
Net:ddr3_control/ck on pin CLK1 on location OLOGIC_X0Y22
    Conflict detected on wire: PINFEED1(-64752,-28286)

Routing Conflict 2:
Net:ddr3_control/ck_dynamic_180 on pin CLK1 on location ILOGIC_X0Y26
Net:ddr3_control/ck on pin CLK1 on location OLOGIC_X0Y26
    Conflict detected on wire: PINFEED1(-64752,-8014)

Routing Conflict 3:
Net:ddr3_control/ck_dynamic_180 on pin CLK1 on location ILOGIC_X0Y28
Net:ddr3_control/ck on pin CLK1 on location OLOGIC_X0Y28
    Conflict detected on wire: PINFEED1(-64752,-4814)

Routing Conflict 4:
Net:ddr3_control/ck_dynamic_180 on pin CLK1 on location ILOGIC_X0Y23
Net:ddr3_control/ck on pin CLK1 on location OLOGIC_X0Y23
    Conflict detected on wire: PINFEED1(-64742,-28254)

Routing Conflict 5:
Net:ddr3_control/ck_dynamic_180 on pin CLK1 on location ILOGIC_X0Y27
Net:ddr3_control/ck on pin CLK1 on location OLOGIC_X0Y27
    Conflict detected on wire: PINFEED1(-64742,-7982)

Routing Conflict 6:
Net:ddr3_control/ck_dynamic_180 on pin CLK1 on location ILOGIC_X0Y29
Net:ddr3_control/ck on pin CLK1 on location OLOGIC_X0Y29
    Conflict detected on wire: PINFEED1(-64742,-4782)

Code: [Select]
// IODDR2 primitives are needed because the 'dq' signals are of double-data-rate
// [url]https://www.xilinx.com/support/documentation/sw_manuals/xilinx14_7/spartan6_hdl.pdf#page=123[/url]

// IDDR2: Input Double Data Rate Input Register with Set, Reset and Clock Enable.
// Spartan-6
// Xilinx HDL Libraries Guide, version 14.7

IDDR2 #(
.DDR_ALIGNMENT("C0"),  // Sets output alignment to "NONE", "C0" or "C1"
.INIT_Q0(1'b0),  // Sets initial state of the Q0 output to 1'b0 or 1'b1
.INIT_Q1(1'b0),  // Sets initial state of the Q1 output to 1'b0 or 1'b1
.SRTYPE("ASYNC")  // Specifies "SYNC" or "ASYNC" set/reset
)
IDDR2_dq_r(
.Q0(dq_r_q0[dq_index]),  // 1-bit output captured with C0 clock
.Q1(dq_r_q1[dq_index]),  // 1-bit output captured with C1 clock
.C0(ck_dynamic),  // 1-bit clock input
.C1(ck_dynamic_180),  // 1-bit clock input
.CE(1'b1),  // 1-bit clock enable input
.D(dq_r[dq_index]),    // 1-bit DDR data input
.R(reset),    // 1-bit reset input
.S(1'b0)     // 1-bit set input
);
// End of IDDR2_inst instantiation


// ODDR2: Input Double Data Rate Output Register with Set, Reset and Clock Enable.
// Spartan-6
// Xilinx HDL Libraries Guide, version 14.7

ODDR2 #(
.DDR_ALIGNMENT("C0"),  // Sets output alignment to "NONE", "C0" or "C1"
.INIT(1'b0),  // Sets initial state of the Q output to 1'b0 or 1'b1
.SRTYPE("ASYNC")  // Specifies "SYNC" or "ASYNC" set/reset
)
ODDR2_dq_w(
.Q(dq_w[dq_index]),  // 1-bit DDR output data
.C0(ck),  // 1-bit clock input
.C1(ck),  // 1-bit clock input
.CE(1'b1),  // 1-bit clock enable input
.D0(dq_w_d1[dq_index]),    // 1-bit DDR data input (associated with C0)
.D1(dq_w_d0[dq_index]),    // 1-bit DDR data input (associated with C1)
.R(reset),    // 1-bit reset input
.S(1'b0)     // 1-bit set input
);
// End of ODDR2_inst instantiation
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7807
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #470 on: August 31, 2021, 03:13:40 am »
Sorry, but I am no expert on Xilinx.

However, with Altera, usually when you want to use the DDR IO buffer's local inversion/clock doubler, usually the second C1 clock input is either left open/unconnected/none and you set a specific parameter for the buffer so it knows to self-generate the 180 degree clock internally, or, you would place the same clock net source as C0 input for C1, except you add a ' ! ' in front of the net name and the compiler will know to use the buffer's internal clock inversion circuitry.

  Separate of DDR3, having a complete new separate clock path for C1 is useful for odd custom phase offset for special purposes.
« Last Edit: August 31, 2021, 03:15:22 am by BrianHG »
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #471 on: August 31, 2021, 04:28:17 am »
Quote
Separate of DDR3, having a complete new separate clock path for C1 is useful for odd custom phase offset for special purposes.

Why new separate clock path ONLY for C1 when DDR_ALIGNMENT is set to C0 ?  Which special purposes were you referring to in the above quoted sentence ?


It seems that both IDDR2_dq_r and ODDR2_dq_w need exactly similar clock inputs for C0 and C1 pins.  Please correct me if my understanding is wrong.

If this is the case, then how exactly would the incoming DQ bits be sampled properly at the middle of a bit ?

« Last Edit: August 31, 2021, 04:33:09 am by promach »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7807
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #472 on: August 31, 2021, 05:05:35 am »
Are you using 2 buffers?  An input and an output?
When Xilinx says C0, C1, are they talking about the clock source for the even and odd latches of the DDR pin buffers?

Maybe asking on Xilinx's forum would be best.

I'm used to dealing with a DDR input, or DDR output manually tied together, or an IO DDR which has the 2 together, except instead of a C0, C1, IE four clocks in the first case, I would have a clock in and a clock out.  Or, a clock in0, clock in1, clock out0, clock out1.
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: DDR3 initialization sequence issue
« Reply #473 on: August 31, 2021, 06:58:44 am »
Quote
Are you using 2 buffers?  An input and an output?
When Xilinx says C0, C1, are they talking about the clock source for the even and odd latches of the DDR pin buffers?

IODDR2 primitive is to handle double-data-rate signal, while IOBUF primitive is to handle FPGA IO pin related signal
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3150
  • Country: ca
Re: DDR3 initialization sequence issue
« Reply #474 on: August 31, 2021, 02:46:50 pm »
Code: [Select]
Routing Conflict 1:
Net:ddr3_control/ck_dynamic_180 on pin CLK1 on location ILOGIC_X0Y22
Net:ddr3_control/ck on pin CLK1 on location OLOGIC_X0Y22

You're doing this again. The C0 pin of IDDR must be connected to the same clock as C0 pin of the corresponding ODDR. The C1 pin of IDDR must be connected to the same clock as C1 pin of the corresponding ODDR. Same clocks must be used with IDELAY/ODELAY if you use delays. I think that internally they are fed by the same wire, so you cannot separate them.

Also, C1 must be 180 degree shift of C0. C1 can be a wire from the source, or can be "not C0" if you use BUFG.

This is not designed for DDR3 memory. This is designed for interfaces where the single clock is produced by FPGA (through BUFG) or by the other side, such as FT600 (through BUFIO). There's no prescribed way to use this for DDR3, you need to re-purpose these things on your own.

Or switch to 7-series which is much better for DDR3.
 
The following users thanked this post: promach


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf