Sign In

Don't have a Xilinx account yet?

  • Choose to receive important news and product information
  • Gain access to special content
  • Personalize your web experience on Xilinx.com

Create Account

Username

Password

Forgot your password?
XClose Panel
Xilinx Home
Reply
Visitor
timplatt
Posts: 12
Registered: ‎02-03-2010
0

DDR2 I/O instantiation in Spartan 6

Using the DDR2 I/O instantion from the thread "BIDI DDR Differential -- simple, right?",

I'm trying to verify the DDR2 connections in my design.  However, I get an error during MAP.

- using ISE 13.1

- 64 bit DDR2 interface

- Spartan6 LX150

 

Here's my code for one of the I/Os:

 

// shell of DQS

  IOBUF  ddr2_dqs0_io  (.I(ddr2_dqs0_out ), .T(ddr2_dqs_ts ), .O(ddr2_dqs0_in ), .IO(ddr2_dqs0p_p ) );
  BUFG  ddr2_dqs0_bufg  (.I(ddr2_dqs0_in), .O(ddr2_dqs0_ing) );
  assign ddr2_dqs0_out = clk;              //clk is the DQS output control

 

// one DDR2 I/O

  IDDR2 #(.DDR_ALIGNMENT("NONE"),
          .INIT_Q0(1'b0),
          .INIT_Q1(1'b0),
          .SRTYPE("SYNC") ) ddr2_dq0_iddr2   (.C0( ddr2_dqs0_ing  ),
                                              .C1(~ddr2_dqs0_ing  ),
                                              .CE(1'b1            ),
                                              .D(Ddr2_dq_ini[0]   ),
                                              .R(1'b0             ),
                                              .S(1'b0             ),
                                              .Q0(Ddr2_dq_in0[0]  ),
                                              .Q1(Ddr2_dq_in1[0]  ) );

  IOBUF  ddr2_dq0_io  (.I (Ddr2_dq_out[0] ),
                       .T (ddr2_data_ts0  ),
                       .O (Ddr2_dq_ini[0] ),
                       .IO(Ddr2_dq_p[0]   ) );

  ODDR2 #(.DDR_ALIGNMENT("NONE"),
          .INIT(1'b0),
          .SRTYPE("SYNC") ) ddr2_dq0_ts_oddr2 (.C0( ddr2_dqs0_ing ),
                                               .C1(~ddr2_dqs0_ing ),
                                               .CE(1'b1           ),
                                               .D0( ddr2_data_ts  ),                   //ddr2_data_ts is the tri-state control
                                               .D1(~ddr2_data_ts  ),
                                               .R(1'b0            ),
                                               .S(1'b0            ),
                                               .Q(ddr2_data_ts0   ) );

  ODDR2 #(.DDR_ALIGNMENT("NONE"),
          .INIT(1'b0),
          .SRTYPE("SYNC") ) ddr2_dq0_oddr2   (.C0( ddr2_dqs0_ing ),
                                              .C1(~ddr2_dqs0_ing ),
                                              .CE(1'b1           ),
                                              .D0(Cntr0[0]       ),                   //Cntr0[0] is just a place holder driver from the internal clock
                                              .D1(Cntr0[0]       ),
                                              .R(1'b0            ),
                                              .S(1'b0            ),
                                              .Q(Ddr2_dq_out[0]  ) );

 

MAP says:

Pack:2531 - The dual data rate register "ddr2_dq0_ts_oddr2" failed to join the "OLOGIC2" component as required.  The output signal for register symbol ddr2_dq0_ts_oddr2 requires general routing to fabric, but the register can only be routed to ILOGIC, IODELAY, and IOB.

 

I've seen this error is some other forums but I didn't see a solution.

 

I know what the message is telling me but I don't see why.  The ODDR2 for the TS shouldn't need to go to the fabric.

It should be a direct connect to the IOBUF.  I've even explored the FPGA editor to see the ODELAY and I think I see what

is trying to occur (i.e. using the FF for TS in the ODELAY).

 

I don't see what the problem is.  Clocking?

 

 

Ultimately, I'm trying to figure out if I can put all the DDR2 signals in a single bank.  My concern is the clocking resources.

If the DQS signals act like clocks and I need 8 BUFGs to support this, will they all fit in a single bank (bank 0

in my case)?

 

I think I will want a BUFIO2 for each of the DQS in the final design but they want to be driven by a BUFG according to what I read in the clocking guide for Spartan 6 so my test case using BUFG should reflect the resources needed?

 

My questions are:

1) What is wrong with my code? (i.e. why doesn't MAP like it)

2) Are the clocking resources in bank 0 sufficient for a complete 64 bit DDR2 SODIMM implementation?

3) Is there a way to see what map is trying to do so I can dig into this a bit deeper myself?


Using your example, I'm trying to verify the DDR2 connections in my design.  However, I get an error during MAP.

- using ISE 13.1

- 64 bit DDR2 interface

- Spartan6 LX150

 

Here's my code for one of the I/Os:

 

// shell of DQS

  IOBUF  ddr2_dqs0_io  (.I(ddr2_dqs0_out ), .T(ddr2_dqs_ts ), .O(ddr2_dqs0_in ), .IO(ddr2_dqs0p_p ) );
  BUFG  ddr2_dqs0_bufg  (.I(ddr2_dqs0_in), .O(ddr2_dqs0_ing) );
  assign ddr2_dqs0_out = clk;              //clk is the DQS output control

 

// one DDR2 I/O

  IDDR2 #(.DDR_ALIGNMENT("NONE"),
          .INIT_Q0(1'b0),
          .INIT_Q1(1'b0),
          .SRTYPE("SYNC") ) ddr2_dq0_iddr2   (.C0( ddr2_dqs0_ing  ),
                                              .C1(~ddr2_dqs0_ing  ),
                                              .CE(1'b1            ),
                                              .D(Ddr2_dq_ini[0]   ),
                                              .R(1'b0             ),
                                              .S(1'b0             ),
                                              .Q0(Ddr2_dq_in0[0]  ),
                                              .Q1(Ddr2_dq_in1[0]  ) );

  IOBUF  ddr2_dq0_io  (.I (Ddr2_dq_out[0] ),
                       .T (ddr2_data_ts0  ),
                       .O (Ddr2_dq_ini[0] ),
                       .IO(Ddr2_dq_p[0]   ) );

  ODDR2 #(.DDR_ALIGNMENT("NONE"),
          .INIT(1'b0),
          .SRTYPE("SYNC") ) ddr2_dq0_ts_oddr2 (.C0( ddr2_dqs0_ing ),
                                               .C1(~ddr2_dqs0_ing ),
                                               .CE(1'b1           ),
                                               .D0( ddr2_data_ts  ),                   //ddr2_data_ts is the tri-state control
                                               .D1(~ddr2_data_ts  ),
                                               .R(1'b0            ),
                                               .S(1'b0            ),
                                               .Q(ddr2_data_ts0   ) );

  ODDR2 #(.DDR_ALIGNMENT("NONE"),
          .INIT(1'b0),
          .SRTYPE("SYNC") ) ddr2_dq0_oddr2   (.C0( ddr2_dqs0_ing ),
                                              .C1(~ddr2_dqs0_ing ),
                                              .CE(1'b1           ),
                                              .D0(Cntr0[0]       ),                   //Cntr0[0] is just a place holder driver from the internal clock
                                              .D1(Cntr0[0]       ),
                                              .R(1'b0            ),
                                              .S(1'b0            ),
                                              .Q(Ddr2_dq_out[0]  ) );

 

MAP says:

Pack:2531 - The dual data rate register "ddr2_dq0_ts_oddr2" failed to join the "OLOGIC2" component as required.  The output signal for register symbol ddr2_dq0_ts_oddr2 requires general routing to fabric, but the register can only be routed to ILOGIC, IODELAY, and IOB.

 

I've seen this error is some other forums but I didn't see a solution.

 

I know what the message is telling me but I don't see why.  The ODDR2 for the TS shouldn't need to go to the fabric.

It should be a direct connect to the IOBUF.  I've even explored the FPGA editor to see the ODELAY and I think I see what

is trying to occur (i.e. using the FF for TS in the ODELAY).

 

I don't see what the problem is.  Clocking?

 

 

Ultimately, I'm trying to figure out if I can put all the DDR2 signals in a single bank.  My concern is the clocking resources.

If the DQS signals act like clocks and I need 8 BUFGs to support this, will they all fit in a single bank (bank 0

in my case)?

 

I think I will want a BUFIO2 for each of the DQS in the final design but they want to be driven by a BUFG according to what I read in the clocking guide for Spartan 6 so my test case using BUFG should reflect the resources needed?

 

My questions are:

1) What is wrong with my code? (i.e. why doesn't MAP like it)

2) Are the clocking resources in bank 0 sufficient for a complete 64 bit DDR2 SODIMM implementation?

3) Is there a way to see what map is trying to do so I can dig into this a bit deeper myself?

Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009

Re: DDR2 I/O instantiation in Spartan 6

[ Edited ]

In the future, it would be helpful if you provided

  • more comments in the code
  • ports for IOs

When the code is all cleaned up and the missing parts are added, the code compiles without errors.  Changes are noted in the comments.

 

module s6_forum_top (
    input ddr2_dqs0p_p,  // BIDI DQS strobe in real life, simple clock input for this example
    inout wire Ddr2_dq_p,
    input infoo1, infoo2,   // bogus inputs to provide fabric signal sources
    output    outfoo1, outfoo2  // dummy outputs to avoid trimming
);

wire Ddr2_dq_out; // signal connection from ODDR2.Q to IOBUF.I

assign Cntr0 = (infoo1 ^ infoo2); // index removed, fabric source for Cntr0
assign outfoo1 = Ddr2_dq_in0 ^ Ddr2_dq_in1;   // fabric load for Ddr2_dq_inx
assign outfoo2 = Ddr2_dq_in0 ^ ~Ddr2_dq_in1;  // fabric load for Ddr2_dq_inx

// shell of DQS
IBUF  ddr2_dqs0_io      // clock input buffer, changed from IOBUF
 (.O(ddr2_dqs0_in ),    // clock input
  .I(ddr2_dqs0p_p ) );  // input port added

BUFG  ddr2_dqs0_bufg  (.I(ddr2_dqs0_in), .O(ddr2_dqs0_ing) );   // clock buffer

// one DDR2 I/O
IDDR2 #(.DDR_ALIGNMENT("NONE"),
     .INIT_Q0(1'b0),
     .INIT_Q1(1'b0),
     .SRTYPE("SYNC") )
ddr2_dq0_iddr2 (
  .C0    ( ddr2_dqs0_ing),
  .C1    (~ddr2_dqs0_ing),
  .CE    (1'b1),
  .D    (Ddr2_dq_ini),    // index removed
  .R    (1'b0),
  .S    (1'b0),
  .Q0    (Ddr2_dq_in0),      // index removed, fabric load pin added
  .Q1    (Ddr2_dq_in1) );    // index removed, fabric load pin added

IOBUF  ddr2_dq0_io (
  .I (Ddr2_dq_out),    // index removed
  .T (ddr2_data_ts0  ),
  .O (Ddr2_dq_ini),    // index removed
  .IO(Ddr2_dq_p) );    // inout port added, index removed

ODDR2 #(.DDR_ALIGNMENT("NONE"),  // tri-state control, DDR rate
    .INIT(1'b0),
    .SRTYPE("SYNC") )
ddr2_dq0_ts_oddr2 (
   .C0( ddr2_dqs0_ing ),
    .C1(~ddr2_dqs0_ing ),
    .CE(1'b1           ),
    .D0(infoo1),   // fabric signal source provided
    .D1(infoo2),   // fabric signal source provided
    .R(1'b0            ),
    .S(1'b0            ),
    .Q(ddr2_data_ts0   ) );

ODDR2 #(.DDR_ALIGNMENT("NONE"),  // data output, DDR rate
  .INIT(1'b0),
  .SRTYPE("SYNC") )
ddr2_dq0_oddr2   (
   .C0    ( ddr2_dqs0_ing ),
   .C1    (~ddr2_dqs0_ing ),
   .CE    (1'b1),
   .D0    (Cntr0),    // index removed
   .D1    (Cntr0),    // index removed
   .R     (1'b0),
   .S     (1'b0),
   .Q     (Ddr2_dq_out) );    // index removed
                          
endmodule

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Visitor
timplatt
Posts: 12
Registered: ‎02-03-2010
0

Re: DDR2 I/O instantiation in Spartan 6

Looking through the changes made, it seems like the most significant change was that the IOBUF for the DQS signal was changed to an IBUF.

 

This breaks the design. i.e. DDR2 reads need the DQS as an input but DDR2 writes need this as an output.

 

How does one drive the DQS signals during a write?  A separate I/O (output)?

Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009
0

Re: DDR2 I/O instantiation in Spartan 6

[ Edited ]

Change it back to an IOBUF, hook up the extra pins correctly, and it 'builds' without errors or warnings.

You have isolated your problem (if any) to the bidi strobe, that should be considered progress.  Agreed?

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009
0

Re: DDR2 I/O instantiation in Spartan 6

In real life (DDR2 memory interface), the IDDR blocks will use the DQS strobe from the memory, and the ODDR blocks will use a clock which is generated internally.  Yes?

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Visitor
timplatt
Posts: 12
Registered: ‎02-03-2010
0

Re: DDR2 I/O instantiation in Spartan 6

Sure.

 

But each of the 8 DQS signals from the DDR2 will need a BUFG (& BUFIO2?) to support the I/Os signal, correct?

 

There are only 16 BUFGs in the Spartan 6.  I have three other pirmary clock inputs in the design plus the DCMs / PLLs (for on-chip created clocks) eat up BUFGs  (feedback, PLL/DCM outputs, etc.).  I think I have enough BUFGs in general.  But...

 

My concern is can the Spartan 6 distribute the 8 DQS I/O clock regions on a single side of a the chip (bank 0 in my case)?

 

I'm willing to either sacrifice differential DQS lines for single ended (or use non-optimal clock locations for the differential

clock inputs - I'm assuming that I can tune the extra delay with the IODELAY or slow down the memory clock).

 

 

Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009
0

custom Spartan-6 DDR2 memory controller

[ Edited ]

But each of the 8 DQS signals from the DDR2 will need a BUFG (& BUFIO2?) to support the I/Os signal, correct?

 

Yes, unless you decide to consolidate/combine DQS for multiple byte lanes, or you can define the DQS timing (at the IDDR2 input blocks) relative to the 'system' clock tightly enough to avoid a separate fabric clock (and BUFG) for each byte lane.

 

My concern is can the Spartan 6 distribute the 8 DQS I/O clock regions on a single side of a the chip (bank 0 in my case)?

 

Don't know.  An hour of trial and experimentation with ISE should provide the answer.

 

I'm willing to either sacrifice differential DQS lines for single ended (or use non-optimal clock locations for the differential clock inputs - I'm assuming that I can tune the extra delay with the IODELAY or slow down the memory clock).

 

It's your design and your decision.  I'm not sure what limitation is overcome with the use of single-ended (rather than differential) DQS in this application.

 

You started this thread with a MAP problem in your use of Spartan-6 IDDR2 and ODDR2 blocks.  I think this problem has been resolved.

 

The bigger problem for you is how to implement a DDR2 SO-DIMM (64bit?) DRAM memory controller.  I am not surprised that this is a project which requires extensive design effort.

 

You correctly note clocking resource limitations in the Spartan-6 family which complicate memory controller designs with many byte lanes.  For guidance, you might want to examine the soft memory controller cores generated by MIG for Spartan-3x and Virtex-5/6 devices.  The full source code is generated by MIG in each of these applications.

 

You might end up compromising the degree of skew normally permitted or tolerated between byte lanes.  This area of compromise is easier to make if you are the primary customer for this memory controller IP.  If you are marketing this IP to others, such additional byte lane timing match requirements may be perceived as a minor or even moderate technical liablility.

 

I wish you well.  This sounds like an interesting project, and you seem to be fully capable of seeing this through to a successful conclusion.

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Visitor
timplatt
Posts: 12
Registered: ‎02-03-2010
0

Re: custom Spartan-6 DDR2 memory controller

        "An hour of trial and experimentation with ISE should provide the answer."

 

This is what I was trying to do which caused the initial MAP problem.  While I did get a single I/O working from your

help above, MAP still complains when I try to implement all 64.  I'm still hacking at it.           8-(

 

      "I'm not sure what limitation is overcome with the use of single-ended (rather than differential) DQS in this  

        application."

 

There are only 8 GCLK pins on a bank.  If you use them differentially there are only 4 (the GCLK pins are differentially paired pins)

 

 

Thanks for your time in helping me try to figure this all out.

 

 

Xilinx Employee
jschmitz
Posts: 412
Registered: ‎10-23-2007
0

Re: custom Spartan-6 DDR2 memory controller

Expert Contributor
eteam00
Posts: 7,505
Registered: ‎07-21-2009
0

Re: custom Spartan-6 DDR2 memory controller

[ Edited ]

"An hour of trial and experimentation with ISE should provide the answer."

 

This is what I was trying to do which caused the initial MAP problem.  While I did get a single I/O working from your

help above, MAP still complains when I try to implement all 64.  I'm still hacking at it.

 

What happens when you try 2, 4, 8, 16, or 32?

Or, more specifically (accounting for 8*DQ + 1*DQS per byte lane), 8+1, 16+2, 24+3, or 32+4 ?

 

There are only 8 GCLK pins on a bank.  If you use them differentially there are only 4 (the GCLK pins are differentially paired pins)

 

Thank you for the explanation.

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.