1

I'm programming a Xilinx Spartan-6 on an OpalKelly implementation for my master thesis at university. To be precise, this is the FPGA I'm working on (XEM6010-LX45): https://www.opalkelly.com/products/xem6010/

It is mounted on a board that has to acquire multiple signals (8+), process them and generate multiple ones (16+) to close some feedback loops based on the settings.

As you can imagine I need to drive multiple DACs and ADCs, but I'm struggling with the correct way to impose timing constraints in the .ucf file.


Let's start from the DACs, we'll talk about the ADCs if we figure this out :D

4 DAC chips, each driven by 4 signals: clock, reset, sync, data. Clock is in common among all DACs and it's a 27MHz clock coming from the PLLs, regenerated with a DDR structure and sent along with the other signals.

I've already come up with the correct timing constraints relative to the external clock (the one I'm sending out) but since that is not the one clocking the data/sync/reset flip flops, it seems I have to impose the constraints relative to the internal clock.

How do I manage this situation, basically a BUS structure with the clock in it?

Timing report is fine except for the fact that every timing is relative to the internal clock, and it's ignoring my REFERENCE_PIN instruction (probably because I use it in the wrong way).

How can I impose timing constraints relative to an output pin? After all, the software should be able to calculate the delay to send the clock out of the FPGA (as it does for every pin), so after that is only a matter of subtractions and bus skew!

Here is the .ucf file I've written (only the part we are interested in):

NET "clk_dac"        TNM_NET = "TNM_clk_dac";
TIMESPEC TS_clk_dac = PERIOD "TNM_clk_dac" 27 MHz HIGH 50%; #27MHz

# DAC SLOW
NET "dac_slow_sync_pin1" TNM = "dac_slow_sync";
NET "dac_slow_sync_pin2" TNM = "dac_slow_sync";
NET "dac_slow_sync_pin3" TNM = "dac_slow_sync";
NET "dac_slow_sync_pin4" TNM = "dac_slow_sync";
NET "dac_slow_data_pin1" TNM = "dac_slow_data";
NET "dac_slow_data_pin2" TNM = "dac_slow_data";
NET "dac_slow_data_pin3" TNM = "dac_slow_data";
NET "dac_slow_data_pin4" TNM = "dac_slow_data";

OFFSET = OUT AFTER "clk_dac" REFERENCE_PIN "dac_slow_clk" RISING;
OFFSET = OUT AFTER "clk_dac" REFERENCE_PIN "dac_slow_clk" FALLING;

TIMEGRP "dac_slow_sync" OFFSET = OUT 24 ns AFTER "clk_dac" REFERENCE_PIN "dac_slow_clk" FALLING;
TIMEGRP "dac_slow_data" OFFSET = OUT 35 ns AFTER "clk_dac" REFERENCE_PIN "dac_slow_clk" RISING;
jww
  • 97,681
  • 90
  • 411
  • 885
FlyerDragon
  • 212
  • 4
  • 16

2 Answers2

2

What works for me on me on slow SDR interfaces like your DAC (I assumed SDR...) is to put all outputs on IOB registers and ensure timings inside the FPGA.

All IOB registers clocked by the same internal BUFG clock will have a very similar clock-to-output values (especially relative to the 27 MHz clock). This is particularly true since the timings delays depends largely on temperature, and temperature can be considered mostly constant across the device.

Usually, you will find you easily meet timings if you either send the clock and data edge-aligned, or only invert the clock. As I said, if the timings are met inside the FPGA, it will still be the case outside if all output are registered in IOB and clocked by the same BUFG. In the case of a DDR interface, sending the clock delayed by 90 degrees (requires a PLL) usually works.

In your kind of case, I don't bother with timings constraints and only ensure all output are registered in IOBs. You should know that constraints doesn't affect either map or place-and-route, as they are only verified. It is the designer's job to make sure the system meets interface timings, the tool only give you the actual value for your design.

On a final note, saying that timings delays will be the same if outputs are registered assumes that outside delays are the same. This won't be the case for you, since it seems the clock feeds several DAC (and thus have a larger capacitance and delay) while the data is directly connected. Then again, you are the one that have to make the necessary adjustments.

Glossary update

SDR: Single Data Rate. Data is transferred on 1 of the clock edges.

DDR: Double Data Rate. Data is transferred on both clock edges.

BUFG: Clock buffer. All your clock should use BUFG, they are special buffer and low skew lines designed for clock.

IOB: Input/Output Block. Special circuit near the IO pad that can be configured to customize the path of your IOs. In particular, it has a register close to the pad. PLL: Phase Locked-Loop. A circuit to modify your clock (frequency/phase).

IODELAY: A special circuit in the IOB to add a constant or programmable delay to your IOs.

I suggest you look at the IOB datasheet. The Xilinx site has also a plethora of datasheet, tutorial and application note.

Jonathan Drolet
  • 3,318
  • 1
  • 12
  • 23
  • In addition: Using IOB registers should be the default for every design, nevertheless it's mostly disabled in in projects... Achieving the timing in logic is a good way, but a proper set of constraints is also required so that STA can cover all paths, even the paths outside of the FPGA. I don't know if Spartan-6 devices have IDELAY and ODELAY primitives, if so, a phase shifted clock or data pin can be generated by these primitives without using/wasting an DCM/MMCM or PLL :) – Paebbels Mar 27 '15 at 07:53
  • Thanks for the answer! I intuitively understand what you both are saying but I'm far from deeply doing that and knowing how to implement what you are suggesting :) please note that I'm self-taught and I'm pretty ignorant on the internal resources differences with their fancy abbreviations and in the use of planahead :-D can you please explain like you were explaining variable types to a C++ novice and link me, if you have some, good tutorials and video tutorials :-) thanks for the patience! Ps: I'm not the one who designed the board and at the moment I have no control on that :/ – FlyerDragon Mar 27 '15 at 09:55
  • @Paebbels, Spartan-6 have IODELAY2 primitives, but lacks the IDELAYCTRL component. Thus, they are really useful for programmable delay with calibration, and have a quite large timings variations when used in fix mode. – Jonathan Drolet Mar 27 '15 at 13:55
  • @JonathanDrolet So you have experience with IODELAY primitives? Can you have a look into my question on EE.SE: [Can I generate a 90° Clock signal with Xilinx's ODELAY for RGMII?](http://electronics.stackexchange.com/questions/161253/can-i-generate-a-90%C2%B0-clock-signal-with-xilinxs-odelay-for-rgmii). I Didn't get any answers or comments :( – Paebbels Mar 27 '15 at 16:30
  • Thanks, I've read a couple of guides on xilinx primitives and resources and now I undestand better what you are suggesting. However I still don't know how to I can impose the use of IOB registers to minimize the skew among the signals. Does it come from the VHDL by registering the outputs of the FSM? Or is it done via .ucf file? For what concerns the bigger capacitance that the clock signal has to drive, if that's a real problem I can maybe find a way with the IODELAY primitive. – FlyerDragon Mar 27 '15 at 17:04
  • @Paebbels Sorry, I'm not that comfortable with them. We don't design much boards and usually use the same interfaces, so I don't delve into their details very often. – Jonathan Drolet Mar 27 '15 at 18:37
  • 1
    @FlyerDragon The IOB registerer usage is automatically controlled by "Implement Design" options. You can also add attributes in VHDL or UCF to bypass the tool's behavior. Finally, at the end of the map report there is a table listing all IOs and whether the IOB register is used, so you can make sure all is right. There are some restriction on IOB registers, for instance, you can't read them back, at least not as easily as normal registers. – Jonathan Drolet Mar 27 '15 at 18:41
2

Additional Resources

There is UG612 - Timing Closure User Guide describing how to specify timing constrains. Chapter 3 contains a general description how static timing analysis (STA) works and what should be defined to evaluate timings. There are also many nice picture to show from where to where a constraint is applied.

And there is UG625 - Constraints Guide describing where you can specify constraints (in ucf, xcf, ncf files, in VHDL/Verilog, ...).

Paebbels
  • 15,573
  • 13
  • 70
  • 139