cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
eteam00
Instructor
Instructor
10,604 Views
Registered: ‎07-21-2009

BIDI DDR Differential -- simple, right?

Jump to solution

I thought I'd take a few minutes to cobble together an example design illustrating bidirectional DDR differential IO (similar to DQS strobe signaling).  I tried to show how wonderful the internal clock inverters in the IDDR2 and ODDR2 blocks are, allowing the use of a single distributed clock.

 

Simple, right?  For some reason, I cannot 'get there'.  ISE 12.4, under my careful and expert guidance, tells me that an extra clock inverter is unavoidable.  I can't figure out how to get the internal clock inversions in the IDDR/ODDR blocks to kick in.  Please tell me where I screwed up (hint:  it may be synth/map process properties).

 

Here's the generated RTL schematic, showing the evil and sinister clock inverter
(note:  click here for full-size image ):

forum_bidi_diff_ddr_rtl.png

 

Here's my glorious and idiot-proof Verilog source code, targeted for S-6, but should also work for S-3e (if pin LOCs are unassigned):

 

module DDR_bidi(
    Clk_100MHz_in,
    out_a, out_b,
    ena_a, ena_b,
    in_a, in_b,
    bidi_p, bidi_n);

input Clk_100MHz_in;  // clock
input out_a, out_b;   // single rate inputs to generate DDR output data
input ena_a, ena_b;   // single rate inputs to generate DDR output enable
output in_a, in_b;    // single rate outputs from DDR data input
inout bidi_p, bidi_n; // bidi, DDR, differential IOs

// DDR data input
IDDR2 IDDR2_x (
    .Q0    (in_a),        // de-muxed data captured on clock posedge
    .Q1    (in_b),        // de-muxed data captured on clock negedge
    .C0    (Clk_100MHz),  // clock input
    .C1    (~Clk_100MHz), // clock input, inverted
    .CE    (1'b1),        // clock enable always
    .D        (in_ddr_d), // DDR data input, from differential buffer
    .R        (1'b0),     // set/reset disabled
    .S        (1'b0) );   // set/reset disabled

// bidirectional differential IO buffer
IOBUFDS # (.IOSTANDARD("BLVDS_25") )    // try BLVDS_25, DIFF_SSTL2_I
    IOBUFDS_x (
    .O     (in_ddr_d),       // input buffer output
    .IO    (bidi_p),         // Diff_p inout (connect directly to top-level port)
    .IOB   (bidi_n),         // Diff_n inout (connect directly to top-level port)
    .I     (out_ddr_d),      // output buffer input
    .T     (out_ddr_ena) );  // 3-state enable, high=input, low=output

// DDR buffer output enable
ODDR2 ODDR2_t (
   .Q     (out_ddr_ena), // DDR rate output enable
   .C0    (Clk_100MHz),  // clock input
   .C1    (~Clk_100MHz), // clock input, inverted
   .CE    (1'b1),        // clock enable always
   .D0    (ena_a),       // sampled on clock posedge, used when clock is HIGH
   .D1    (ena_b),       // sampled on clock negedge, used when clock is LOW
   .R     (1'b0),        // set/reset disabled
   .S     (1'b0) );      // set/reset disabled

// DDR output data to IO buffer
ODDR2 ODDR2_d (
   .Q     (out_ddr_d),   // 1-bit DDR output data
   .C0    (Clk_100MHz),  // clock input
   .C1    (~Clk_100MHz), // clock input, inverted
   .CE    (1'b1),        // clock enable always
   .D0    (out_a),       // sampled on clock posedge, output when clock is HIGH
   .D1    (out_b),       // sampled on clock negedge, output when clock is LOW
   .R     (1'b0),        // set/reset disabled
   .S     (1'b0) );      // set/reset disabled

IBUFG clkout2_buf     // buffer the source clock input
(.O   (Clk_100MHz),   // use this for the global clock
 .I   (Clk_100MHz_in) );

endmodule

 

Hey, there's a bonus head-scratcher for the ISE wizards:  After cramming this clock inverter down my Verilog throat, ISE complains in BITGEN (but not in synth/map/PAR) that the design has a fatal DRC error.  Talk about adding insult to injury!

 

Here's the (ISE12.4) BITGEN error message:

ERROR:PhysDesignRules:2003 - Unsupported clocking structure. Inversion programming for block out_ddr_d pin CLK1 (INVERTED) must match programming for block out_ddr_d pin CLK0 (NOT INVERTED) when using a shared clock inversion source.

 

Thanks, guys.  It really helps to have a lifeline out there!

 

-- 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.
Tags (1)
0 Kudos
1 Solution

Accepted Solutions
bwade
Scholar
Scholar
13,102 Views
Registered: ‎07-01-2008

Yes, that's correct. The inversion is modeled as if it is internal to the ILOGIC/OLOGIC block but in hardware it isactually in the switchbox path. The RTL scematic is still the logical design and so it's normal to represent the inversion as a gate.

View solution in original post

0 Kudos
7 Replies
bwade
Scholar
Scholar
10,569 Views
Registered: ‎07-01-2008

The inversion actually occurs at the switchbox in this case and not at the ILOGIC/OLOGIC components. Note that the DRC error does not occur until after routing. It looks like the problem is due to the routing and not the circuit configuration. It's hard to examine the details of the routing but it looks like the inverted path is only drving one of the four pins.  I have found an open CR 618807 agains the router for this issue. It was scheduled to be fixed in 13.3 but hasn't been marked fixed yet, so that will probably slip.

 

 

 

 

Tags (1)
eteam00
Instructor
Instructor
10,566 Views
Registered: ‎07-21-2009

Bwade,

 

Thanks for the followup.

 

The inversion actually occurs at the switchbox in this case and not at the ILOGIC/OLOGIC components.

 

Is this comment (above) describing the nature of a synth/map bug, or are you clarifying (correcting) the true implementation of the 'internal polarity selection' as described in the IDDR2 and ODDR2 primitives .C0 and .C1 port descriptions?

 

The rest of this post assumes that the 'external' inverter in the switchbox (rather than internal to the IDDR2/ODDR2 blocks) is a *bug*.

 

As this design example is quite typical (and popular) for forwarding a global clock to a device output, the unwanted inference of a switchbox inverter is more than a trivial inconvenience for some Spartan-6 designers.

 

I haven't done the timing analysis to compare using the internal clock inversion(in the IOB, using the IDDR2 and ODDR2 primitives) against the switchbox inversion.  Do you know off-hand (if you do, this would save me some tedious effort) if:

 

  1. Is this circuit implemented correctly in ISE 11 (or any ISE version available for download/install) ?
  2. In ISE 12/13 where this circuit implementation is incorrect, can correct implementation be achieved using FPGA Editor?
  3. Is this a problem unique to Spartan-6, or are other device families similarly affected?
  4. Other than generating clock + clock_not, are there any other known or recommended workarounds for Spartan-6?

I'm somewhat embarassed, having 'sold' single-clock IDDR/ODDR implementations to many forum users over the last year or so.  Hopefully this problem is limited to Spartan-6 family.

 

-- 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.
0 Kudos
bwade
Scholar
Scholar
10,554 Views
Registered: ‎07-01-2008

Hi Bob,

 

I was able to get this design to work by instantiating a BUFG between the IBUFG and the clock loads. You could also add BUFFER_TYPE = "BUFG" to the output net. I think the root cause of this issue is that the router only handles the inversions correctly if the clock net is driven by a global buffer.

 

This is not a synth/map issue except that maybe you were expecting a BUFG to be inferred by the IBUFG alone. I'm told XST doesn't work that way. Regarding the switchbox inversions, here is a more detailed drawing. The switchbox inversion will be turned on for all routes going to inverted pins. It's up to the router to ensure that each inverted path only drives inverted pins and vice versa. That's why I think this is purely a routing issue.

 

Bret

 

 

 

bwade
Scholar
Scholar
10,547 Views
Registered: ‎07-01-2008

I've checked the CR 618807 test case and found that a local clock was involved there too. This backs up my contention that local clock routing is the root cause.

0 Kudos
eteam00
Instructor
Instructor
10,538 Views
Registered: ‎07-21-2009

bwade, a clarification please...

 

Taking the IDDR2 and ODDR2 primitive descriptions at face value (sometimes ill-advised, based on previous experience), the clock polarity inverters are *internal* to the primitive.  This is why the generated RTL schematic, with *external* clock inverter, seems *wrong*.

 

Are you saying that the clock inverters for a given IOLOGIC (or IOB?) block are located in the switchboxes, and the router provides the connections to make the function *equivalent* to the 'internal' clock polarity inverters in the IDDR2/ODDR2 primitives?

 

Let me re-phrase this, and correct me if I'm wrong:

The internal clock polarity inverters in the IDDR2/ODDR2 clocks are 'logical' rather than physical inverters.  The inversion is physically accomplished in the switchbox associated with each IOB (or is it IOLOGIC?), which is external to the IDDR2/ODDR2 in actual (physical) practice.

 

If my understanding of your explanation in correct, then the discrete series inverter which shows up in the RTL schematic is of no concern, and the RTL schematic is a more accurate depiction of physical implementation than the IDDR2/ODDR2 descriptions in the SelectIO Resources User Guide (UG381) -- Table 2-2 and Table 2-5.

 

I'm looking forward to your review of these comments.  Your help is much appreciated.

 

-- 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.
0 Kudos
bwade
Scholar
Scholar
13,103 Views
Registered: ‎07-01-2008

Yes, that's correct. The inversion is modeled as if it is internal to the ILOGIC/OLOGIC block but in hardware it isactually in the switchbox path. The RTL scematic is still the logical design and so it's normal to represent the inversion as a gate.

View solution in original post

0 Kudos
eteam00
Instructor
Instructor
10,529 Views
Registered: ‎07-21-2009

Summary:

 

The following applies to Spartan-6 family devices.

 

1.  The 'internal' clock polarity inverters in IDDR2 and ODDR2 port descriptions are implemented in switchbox interconnect resources which are nominally external to the IDDR/ODDR2 blocks.  The result is the same, either way, but don't be alarmed if the 'internal' clock polarity inverter shows up in the RTL schematic as a separate inverter.

 

2.  IBUFG is not a BUFG.  It is an IBUF which the synth/map tools locate at a clock pin.  If you want to drive a global clock or IO clock, you need to explicitly instantiate a proper buffer (e.g. BUFG).  If you try to drive a global or IO clock with an IBUFG, a bug in ISE 12.x and 13.x (through 13.2, at least) allows the error to go unchecked through synth/map/place/route.  The error is not caught until the DRC check included in the BITGEN process.

 

Thanks again to bwade for his thorough help on this.

 

-- 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.
0 Kudos