UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor kingc
Visitor
27,571 Views
Registered: ‎07-16-2015

How to constraint Same-Edge capture edge-aligned DDR input properly?

Hi all,

 

I understand that this question has been asked in different ways but it seems that I don't really find the exact match to my question from the web... Looking for some expertise help in here...

 

I have a Source Synchronous Edge-Aligned DDR Input from a NAND memory - the clock is the DQS and the data is the DQx pins.

This is the diagram of what the data output from the NAND looks like.

 

nvddr2_data_output.JPG

 

Since the data is edge aligned and the DQS "clock" ends before the last data valid window, I would need to either use (1) a free-running local clock to match the phase of the DQS "clock" or (2) I would do a 90degree phase shift of the DQS "clock". Since the DQS "clock" is not running all the time plus it is bi-directional, I would not be also to perform a 90degree phase shift at all using MMCM/PLL so the 2nd idea is axed. The first solution is that the DQS/DQ arrival time is not guranteed on every data output period so adjusting the phase of the free-running clock seems to be complicated so I axed this idea also.

 

I am running it quite slow so that my final solution is to put an idelay2 block on the DQS pin to make the "clock" delayed long enough to meet the setup time requirement. This is working for me to capture the data from my 1st attempt (and the delayed clock & non-delayed data goes into FIFO) with some I think it is wrong set_input_delay constarints...

 

In one of the other discussion Constraining Source Synchronous Edge-Aligned DDR Input the input delay constaints make sense but I am not too sure how to convert it into XDC format.

 

 

Original in the thread:

OFFSET = IN -0.1ns VALID 3.8ns BEFORE clock RISING;
OFFSET = IN -0.1ns VALID 3.8ns BEFORE clock FALLING;


What it would be for my case:

OFFSET = IN -0.4ns VALID 58.8ns BEFORE clock RISING;
OFFSET = IN -0.4ns VALID 58.8ns BEFORE clock FALLING;

Data will have a tDQSQ skew of 0.4ns from edges of DQS, and it is valid for tQH (37% of the tRC - 37%*160ns) of 59.2ns from edges of DQS (59.2-0.4) = valid window size of 58.8ns.

 

Now when i think about it in XDC format, I have something like this (note, 59.2 is the tQH, I think the -min here is not focusing on the data valid window size compare to UCF format):

Rising Edge:
set_input_delay -clock DQS_clk -max 0.4 [get_ports DQ[*]];
set_input_delay -clock DQS_clk -min 59.2 [get_ports DQ[*]]];

Falling Edge:
set_input_delay -clock DQS_clk -max 0.4 [get_ports DQ[*]]] -clock_fall -add_delay;
set_input_delay -clock DQS_clk -min 59.2 [get_ports DQ[*]]] -clock_fall -add_delay;

Then when Vivado perform the timing analysis of the SETUP time, it assumes that my data path starts from the rising edge of the DQS clock and destination clock (latch clock) will be the falling edge of the DQS clock.

This gives a massive slack time - 80.907ns because it thinks I don't want to capture on the same edge but the opposite (I believe, the opposite edge timing calculation gives a much more tighter timing 50% than a same edge but next clock analyzsis and it is a DDR path).

 

Thinking in my mind that with the 80.907ns slack if I minus the 80ns half clock period (to make it like same edge capture), I will have a 0.907ns slack time which is good and why it is working?

 

For the HOLD time analysis, it is performing a rise-clock to rise-clock analysis and I will have a massive 46.158ns hold slack because it calculates a input delay of 59.2ns plus some data path delay totaling 62.633ns and the clock have arrived long ago at 16.475ns. This looks about right then?

 

Some question here:

  1. How do I make the timing analysis to be "Same Edge"? Do I have to make a virtual clock at the DQS pin, and another generated clock after the IDELAY? But generated clock only works for MMCM/PLL?
  2. Did I got my -max and -min wrong in the set_input_delay? -max is aiming for the delay skew from the clock edge that affects the setup time, and the -min is aiming for how long the data last from the clock edge that affects the hold time?

Thank you all for the expertise and the time to read through my question. Much apperciated and thank you again for your kind help.

 

Tags (1)
0 Kudos
13 Replies
Historian
Historian
27,404 Views
Registered: ‎01-23-2009

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

So, first of all, it looks like what you are trying to do is probably the correct thing - you need to push the DQS forward to capture each data window, and you should be using an IDELAY on the DQS to do that.

 

I am not sure what you plan to do after that, since the DQS doesn't run continuously and is bidirectional, you will have to determine which captures of the DQ are "real data" and which ones aren't (which DQS edges are part of the read, and which are from the line floating and/or from writes). Then the "real data" will need to be transferred to a static domain - you might need to use a clock crossing FIFO for that...

 

But, your problem is the constraints. There is a solution for this, but its somewhat complicated. This thread is a bit old, so before I go into it, I want to know if you are still looking for a solution - if so, post a reply to this, and I will go into the details of the constraints.

 

Avrum

0 Kudos
Visitor kingc
Visitor
27,382 Views
Registered: ‎07-16-2015

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

Hi avrumw,

 

Thanks for your reply on confirming that my thought of using the idelay to push forward the DQS line in this case.

Yes, I have put in logics to make sure that the clock crossing reading FIFO only capture the real data when we want to perform a NAND read operation.

 

I am still looking for a solution for the timing constraints. Of course I moved on to work on other things as "it is working" at this moment but the super huge positive slack times still bugs me from time to time.

 

At one point, I have added half of the clock period to the -max constraint so that it "covers up" the opposite edge calcuation to make it small like this...

 

Rising Edge:
set_input_delay -clock DQS_clk -max 80.4 [get_ports DQ[*]];
set_input_delay -clock DQS_clk -min 59.2 [get_ports DQ[*]]];

Falling Edge:
set_input_delay -clock DQS_clk -max 80.4 [get_ports DQ[*]]] -clock_fall -add_delay;
set_input_delay -clock DQS_clk -min 59.2 [get_ports DQ[*]]] -clock_fall -add_delay;

And with this I get a 0.9ish positive slack and this is more "reasonable"... just a placebo effect to my mind only. I am looking forward to take up your complicated solution for it and once again, thank you very much for your input.

 

Best
kingc

0 Kudos
Historian
Historian
27,325 Views
Registered: ‎01-23-2009

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

OK...

This is going to be long and complicated. My suggestion, if you really want to follow this, grab a piece of paper and sketch both the circuit and the waveforms as I describe them...

I know your period is large, but I am going to base my constraints on a 10ns DDR interface with a 0.4ns clock/data skew. For the moment, I will assume the clock is a perfect 50% duty cycle.

First, lets understand how the static timing analysis sees these elements. Lets start with the IDDR. From the static timing analysis point of view, this is really two flip-flops; one clocked on the rising edge of the clock and one clocked on the falling edge of the clock.

Now lets get started on constraints. First I am going to define the clock. As will become evident later, I will need two different clocks for this - one clock for driving the FPGA and one for driving the "external device" (used for the set_input_delay). These will be identical in terms of their properties (period, phase, duty cycle) but I need two different ones for the constraints. In Vivado all clocks are related by default, so even though I define two clocks, they are effectively the same if they have the same attributes

create_clock -name fpga_clk -period 10 [get_ports fpga_clk_pin]
create_clock -name virt_clk -period 10

Now I am going to define the input delays. I will revisit this later, but for now lets use the "simple" ones (these will eventually be the ones for the "correct way" solution)

set_input_delay -clock virt_clk 0.4 [get_ports data_in]
set_input_delay -clock virt_clk -0.4 -min [get_ports data_in]
set_input_delay -clock virt_clk 0.4 [get_ports data_in] -clock_fall -add_delay
set_input_delay -clock virt_clk -0.4 -min [get_ports data_in] -clock_fall -add_delay

Again, lets look at the structure of this. From the STA point of view, we are defining two external flip-flops; one clocked on the rising edge of the clock and one clocked on the falling edge of the clock.

Thus (and you may want to draw this), we have two external FFs (one on each edge) coming together (don't worry about any form of MUX), then going through the data_in port and ending at the IDDR which are two internal flip-flops (one on each edge). So from the static timing point of view, we have FOUR paths (yes FOUR paths)

  • a) from rising edge external FF to falling edge internal FF
  • b) from falling edge external FF to rising edge internal FF
  • c) from rising edge external FF to rising edge internal FF
  • d) from falling edge external FF to falling edge internal FF

Two of these are clearly false (or at least redundant), but all 4 of these will become important later.

Now lets look at how the static timing engine determines launch and capture edges.

The constraints above define two windows of valid timing. The first window is launched by the rising edge of the external FF (since it is described by the set_input_delay commands without the -clock_fall); it starts at time 0.4, and ends at time 4.6 (this isn't technically true, but its good enough for this description). The second window is (created by the set_input_delay with the -clock_fall) starts at 5.4ns and ends at 9.6.

Lets assume that you will use an IDELAY on the clock coming in to the FPGA and delay it by 2.5ns (to place it in the middle of the eye - again, this probably isn't the correct thing to do, since the FPGA has an asymmetric setup/hold requirement, but its good enough for illustration).

So draw the launch clock, which is the virtual clock (virt_clk), it has rise edges at 0ns and 10ns and fall edges at 5ns and 15ns.

Draw the data windows below that, as described above (0.4 to 4.6, and 5.4 to 9.6)

Draw the fpga  clock (fpga_clk) below that (which has the same edges as the virtual clock, edges at 0, 5, 10, 15)

Draw the delayed internal clock, with rising edges at 2.5 and 12.5, and falling edges at 7.5 and 17.5.

Now, lets look at the "rule" for multiple clocks in Vivado. To determine which edge is the capture edge, Vivado looks at the un-propagated clocks (thus fpga_clk and virt_clk). If data is launched on one edge, it is by definition captured on the un-propagated clock edge that follows it in time.

Now we have to look at all 4 of the above paths

  • a) launched from rising edge virt_clk @0ns, the falling edge of fpga_clk that follows it is at 5ns
  • b) launched from falling edge virt_clk @5ns, the rising edge of fpga_clk that follows it is at 10ns
  • c) launched from rising edge virt_clk @0ns, the rising edge of fpga_clk that follows it is at 10ns
  • d) launched from falling edge virt_clk @5ns, the falling edge of fpga_clk that follows it is at 15ns

The actual capture would happen on the propagated clock 2.5ns later, but that's irrelevent for determining the edges.

Clearly if a) passes its setup check, then so will c) (since it has 5ns more time), so the c) path is redundant. The same is true of d); if the b) path passes, the d) path will.

So looking at this, none of these are what we want. We really want

  • launched from the rising edge of virt_clk @0ns, captured at the propagated fpga_clk at 2.5ns, which is the un-propagated clock of fpga_clk at 0ns
  • the same for the falling edge (launched at 5ns, captured at 5ns).

So, we have two ways of doing this - the "cheating way", which is a bit simpler, and the "correct way".

Lets start with the "cheating" way, which is what is done by the language templates in Vivado - do "Windows -> Language Templates" and select "XDC -> Timing Constraints -> Input Delay Constraints -> Source Synchronous -> Edge Alinged (Clock directly to FF) -> Dual Data Rate (DDR).

This mechanism uses the definitions above to "lie" to the tool. Lets look at path a). We know that the tool assumes that the window defined by the risinge edge of virt_clk @0ns will be captured by the falling edge of fpga_clk at @5ns. But, we want the window at 5.4 to 9.6 to be the window captured by the falling edge of fpga_clk, so lets lie. Instead of having the window generated by the rising edge of virt_clk be from 0.4 to 4.6, lets lie to the tool at say that the rising edge of virt_clk really generates the window at 5.4 to 9.6. This is done not by the set_input_delay commands shown above, but by a set with a constant 5ns (1/2 of the clock period) added to all timing. Thus

set_input_delay -clock virt_clk 5.4 [get_ports data_in]
set_input_delay -clock virt_clk 4.6 -min [get_ports data_in]
set_input_delay -clock virt_clk 5.4 [get_ports data_in] -clock_fall -add_delay
set_input_delay -clock virt_clk 4.6 -min [get_ports data_in] -clock_fall -add_delay

This is what the language template and the clocking wizard get you to do; if you use the language template with all 4 skew values being 0.4 and the input_clock_period as 10, you will get the above constraints.

So now, the rising edge of virt_clk at time 0 will generate the window at 5.4 to 9.6. By the rule (for path a), since it is launched by virt_clk at time 0, it will be captured by fpga_clk at time 5ns. This will be delayed internally to 7.5ns, so the window from 5.4 to 9.6 will be captured at 7.5. This is what we want!

So paths a) and b) will give you what you want, paths c) and d) are redundant - they will still be timed but if a) and b) pass, then so will c) and d).

So, what's wrong with this. First, it is lying - its not really what is happening; the rising edge of virt_clk isn't really creating the window at 5.4 to 9.6, its generating the window at 0.4 to 4.6. It also gives you (at least) one significant problem; what if the clock duty cycle isn't 50%? How do you continue the lie to adjust for this fact? It can be done, but it gets increasingly messy.

OK, so now the right way. I am warning you, its pretty complicated...

So, lets start back at the original constraints; the create_clock for fpga_clk and virt_clk and the original set of set_input_delays (without the 1/2 clock period added).

As I said before, these aren't what you want. The default capture edges are not what you want. For example, for the launch edge at 0ns, you want to get it to use the capture edge at 0ns, instead of the default one, which will be at 5ns (for path a) and at 10ns (for path c).

So, how do we change this. The answer is (drum roll please!) - with the set_multicycle_path command!

This is, in fact, exactly what the set_multicycle_path command does - it changes which edge is used for capture. Normally, the capture edge is one clock after the launch edge (which is an edge count of 1). When we do set_multicycle_path 2 for a path, we are changing the capture edge to be 2 clocks later (instead of the default of one edge later). This is why it is called "multi-cycle" - we usually use it to give a path multple cycles to propagate.

But once we realize that what it is doing is changing the capture edge (at least by default), we can use this here. But instead of wanting to move the capture edge forward (from 1 to 2) we want to move it backward (from 1 to 0). So, we use this command

set_multicycle_path 0 -from [get_clocks virt_clk] -to [get_clocks fpga_clk]

This effectively pulls the capture edge back by one full clock period.

So now lets look at our four paths

  • a) Launch  at 0ns to capture a -5ns (from 5ns pulled back one complete clock period)
  • b) Launch at 5ns to capture at 0ns (from 10ns)
  • c) Launch at 0ns to capture at 0ns (from 10ns) - this is the correct one!
  • d) Launch at 5ns to capture at 5ns (from 15ns) - this is the other correct one

 Clearly, though, now a) and b) are not just incorrect, but they will fail. So we need to disable them

set_false_path -setup -rise_from [get_clocks virt_clk] -fall_to [get_clocks fpga_clk]; # diable a)
set_false_path -setup -fall_from [get_clocks virt_clk] -rise_to [get_clocks fpga_clk]; # diable b)

This is (by the way) why I need the two clocks to be separate; I need the -rise_* and -fall_* to refer to clock edges, so I need separate clocks for this.

So now we have the correct setup checks. The hold checks are even more complicated; I won't go through the details, but they need these:

set_multicycle_path -1 -hold -from [get_clocks virt_clk] -to [get_clocks fpga_clk]
set_false_path -hold -rise_from [get_clocks virt_clk] -rise_to [get_clocks fpga_clk];
set_false_path -hold -fall_from [get_clocks virt_clk] -fall_to [get_clocks fpga_clk];

Now we have all the setup and hold checks being done correctly! (Yay!)

But I said I would come back to the duty cycle...

Lets say the duty cycle of the clock is unknown 40/60 to 60/40. This means the falling edge of the clock can be anywhere between 4ns and 6ns (instead of 5ns).

You could deal with this by just effectively increasing the 0.4ns "skews" and add an additional 1ns to them (which would probably work), but you can also do this "correctly"

NOTE: This didn't fully work in an earlier version of Vivado, and I haven't tested it recently...

You can change the duty cycle of the clock using the set_clock_latency command. This command allows you to add latency to the clock on both the rising edge and falling edge and for both min and max delays. So we can do

set_clock_latency -source -fall  -min -1 [get_clocks {virt_clk fpga_clk}]
set_clock_latency -source -fall -max 1  [get_clocks {virt_clk fpga_clk}]

(thus adding -1ns min and +1ns max to the falling edge while leaving the rising edges alone)

So, that's it. Simple, eh?

Avrum

Tags (1)
Visitor kingc
Visitor
27,170 Views
Registered: ‎07-16-2015

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

Hi avrumw,

 

Thank you so much for your great response! Your responses has taught me so much more things than I have expected! Now I know what does the virtual clock "relates" to fpga clock in vivado means. How IDDR is really 2 FF and thus STA will think of the 4 timing paths. Why and how to make a "0 delay" multi-cycle path. How STA in Vivado looks at the "un-propagated" clocks. Even the "Language Templates" are a hidden gem to me. Anyway, back from the excitment...

 

Ah, that's how we "cheat" to make the data "delayed" so that the data at the rising launch clock @0ns, data at the falling launch clock @5ns, will land on capture clock @5ns and @10ns. What I have done in my previous post, is actually utilized this "cheating" method to get to what I wanted. This is also relying on that I am hoping the NAND is pumping out a nice enough 50% duty cycle clock, but this is risky and I will switch to the correct way.

 

With the correct way, path a) & b) is not ture and false pathed for the setup checking - taken this now. Hold time checking I am now trying to digest it (I trust your suggestions but I want to see if I can understand it myself also) because of the "-1" settings - also taken this.

 

All in all, I will also try the set_clock_latency on 2015.1 and I will report the result here once I have done it!

 

Thanks Avrum again and you are very helpful and informative!

Cheers,

kingc

 

 

0 Kudos
Scholar ronnywebers
Scholar
26,113 Views
Registered: ‎10-10-2014

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

Hello @avrumw, you redirected me from this post to here, thanks for that.

 

One question : referring to your 'non-cheating way' explanation : I'm a bit confused about the set_multicycle_path explanation:

This is, in fact, exactly what the set_multicycle_path command does - it changes which edge 
is used for capture. Normally, the capture edge is one clock after the launch edge (which is an
edge count of 1). When we do set_multicycle_path 2 for a path, we are changing the capture edge
to be 2 clocks later (instead of the default of one edge later).

 "normally, the capture edge is one clock after the launch edge"

-> in a SDR with data launched on rising edges, this would mean the next rising edge (an entire clock period (10ns) later),

-> but in a DDR system, does this mean that the next edge is the 'oposite' of the launch edge? So for data launched on the rising edge, the capture edge is only 'half a clock period' (5ns) later.

 

when I was looking at my timing diagrams, which I have drawn on paper as you suggested, I was asuming that the set_multicycle_path would shift the capture edge by only half a clock period (5ns), not an entire clock_period (10ns), because we're dealing with a DDR case here. But I guess this is not the case?

 

So the way to interpret the first set_multicycle_path constraint is (?) : take the fpga_clk clock on the diagram, and shift it an entire clock cycle (of 10ns) backwards, leaving all the 'arrows' connected between launch/capture edges

 

 

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Historian
Historian
26,097 Views
Registered: ‎01-23-2009

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

but in a DDR system, does this mean that the next edge is the 'oposite' of the launch edge? So for data launched on the rising edge, the capture edge is only 'half a clock period' (5ns) later.

I suppose I can be more precise in the terminology...

"Normally the capture edge is the first active edge of the clock at the endpoint that follows the active edge of the clock at the startpoint"

(The two definitions become the same when talking about a path that starts and ends on the same clock).

Now, in this system, as to whether the capture edge is 1 clock period or 1/2 clock period after the launch edge, it depends on which path we are talking about. It is precisely for this reason that we have to understand that this DDR interface consists of four separate paths - the four paths labelled a, b, c, and d in my earlier post. Each of these paths is a normal SDR path (in fact, there is no concept of a "DDR path" in SDC/XDC).

So, for path c), the launch edge is the rising edge of the external FF at time 0, and the capture edge is the rising edge of the internal FF at time 10 - this is "first active edge of the clock at the endpoint that follows the active edge of the clock at the startpoint". When this path is modified by the set_multicycle_path 0 (and all 4 paths are affected), then the capture edge moves to the previous active edge of the clock at the endpoint; this is the rising edge at time 0. It cannot be moved back to the falling edge at time 5, since this path's endpoint is not clocked on the falling edge of the clock.

For path a), the launch edge is the rising edge of the external FF at time 0. The endpoint on this path is clocked on the falling edge of the internal clock. Therefore  the "first active edge of the clock at the endpoint that follows the active edge of the clock at the startpoint" is the falling edge at time 5ns. When this is modified by the set_multicycle_path 0, it is moved back to the previous active edge for this path, which is the falling edge at time -5ns.

Avrum

Tags (1)
Scholar ronnywebers
Scholar
26,095 Views
Registered: ‎10-10-2014

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

thanks @avrumw that is incredibly clear to me!

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Adventurer
Adventurer
22,135 Views
Registered: ‎01-09-2014

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

Hi All,

 

hard to read? take a look at some pictures

 

https://www.altera.com/support/support-resources/design-examples/intellectual-property/exm-tse-rgmii-phy.html

 

take a look at AN477 as well

 

 

Cheers

Observer ajroth
Observer
18,242 Views
Registered: ‎04-14-2015

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

"Lets assume that you will use an IDELAY on the clock coming in to the FPGA and delay it by 2.5ns (to place it in the middle of the eye - again, this probably isn't the correct thing to do, since the FPGA has an asymmetric setup/hold requirement, but its good enough for illustration)."

 

avrumw comments have been super helpful but it seems thing conflict online and still I'm relatively confused...

 

option 1- how much should I idelay my input clk?

If I need to shift an input clk to be in the "middle-ish" of the data windows, how do I know how much to delay it by?

I figured smac middle was safe but below is stated that I should account for the asymmetric setup/hold requirements, how do I tell what these are?  I have an input clk with period 3.846 ns (260 MHz) which the data and clk are source synchronous DDR, however there is a .3 to .55 ns skew from edge of clk to the data, I think data follows the clk edge from min of .3 to max of .55 ns.  I'm going to idelay the clk by about 90deg about  3.846/4 = .9615 ns so it is on center window.  I believe when my rising edge clk hits my iddr it will register my previous falling edge data, and the following falling edge will register the external device rising edge launched data.  Does this sound correct?

 

option 2- I have the option to just skew the data and clk so it comes in at 90 degrees from the external device.  If I do this do I need a virtual clock then?  If so I've seen it done 2 ways, some set their waveform on the external virtual clk to be shifted so my 260 MHz clk would be: create_clock -period 3.846 -name virt_clk -waveform {0.962 2.8845}

or should I do the {0 1.923} for the external virtual clock and internal shift it?  I was confused by avrumw's comment about this as well.   I think if I do option 1 I can just use my fpga clock for everything and don't need a virtual clock but with option 2 I need a virtual clock?

 

THANKS!

0 Kudos
Participant michaeltymcnamara
Participant
6,912 Views
Registered: ‎07-08-2013

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

Great article.  But it has a small typo with huge implications!

 

The article specifies adding set_false_path constraints, using the command  get_clock

The actual command is named get_clocks, and back in the day, as Vivado's tcl interpreter would string-completed that to get_clocks  it worked just fine  ...  until Xilinx added the command get_clock_regions. 

 

 

So today, the [get_clock fpga_clk] prints a message about ambiguity and returns nothing; and hence the set_false_path has no effect.

 

Article has:

 

set_multicycle_path -1 -hold -from [get_clocks virt_clk] -to [get_clocks fpga_clk]

set_false_path -hold -rise_from [get_clocks virt_clk] -rise_to [get_clock fpga_clk];

set_false_path -hold -fall_from [get_clocks virt_clk] -fall_to [get_clock fpga_clk];

 

With current Vivado (2016 and newer) they must be as below (this would have worked then as well)

 

set_multicycle_path -1 -hold -from [get_clocks virt_clk] -to [get_clocks fpga_clk]

set_false_path -hold -rise_from [get_clocks virt_clk] -rise_to [get_clocks fpga_clk];

set_false_path -hold -fall_from [get_clocks virt_clk] -fall_to [get_clocks fpga_clk];

Historian
Historian
6,888 Views
Registered: ‎01-23-2009

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

Thanks for catching that - I have updated the original post to fix the typo.

 

Avrum

0 Kudos
Participant michaeltymcnamara
Participant
6,869 Views
Registered: ‎07-08-2013

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

It takes a community to make the Community Forum work!

0 Kudos
5,656 Views
Registered: ‎11-07-2018

Re: How to constraint Same-Edge capture edge-aligned DDR input properly?

Hi avrumw,

I write xdc for RGMII.

The sch of the FPGA:

输入.png

The time of phy:

phy 时序.png

the xdc:

set rx_clk [get_clocks -of [get_ports rgmii_rxc]]

create_clock -name design_1_eth_mac_0_rgmii_rx_clk -period 8

set_input_delay -clock [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -max 0.5 [get_ports {rgmii_rxd[*] rgmii_rx_ctl}]
set_input_delay -clock [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -min -0.5 [get_ports {rgmii_rxd[*] rgmii_rx_ctl}]
set_input_delay -clock [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -clock_fall -max 0.5 -add_delay [get_ports {rgmii_rxd[*] rgmii_rx_ctl}]
set_input_delay -clock [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -clock_fall -min -0.5 -add_delay [get_ports {rgmii_rxd[*] rgmii_rx_ctl}]

set_false_path -setup -rise_from [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -fall_to $rx_clk
set_false_path -setup -fall_from [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -rise_to $rx_clk
set_false_path -hold -rise_from [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -rise_to $rx_clk
set_false_path -hold -fall_from [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -fall_to $rx_clk

set_multicycle_path 0 -from [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -to $rx_clk
set_multicycle_path -from [get_clocks design_1_eth_mac_0_rgmii_rx_clk] -to $rx_clk -hold -1

The slack of setup is -1.6ns:

setup slack.png

The slack of hold is 2.5ns:

hold.png

What is wrong? Thank you.

 

0 Kudos