Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
The Intel sign-in experience has changed to support enhanced security controls. If you sign in, click here for more information.
19997 Discussions

DQS Input and Output Timing Constraints

Honored Contributor II



I have a DDR controller which has a bidirectional DQS (data strobe) signal. In read states, the DDR device is driving DQS, as well as some data bits which have timing relationship to the input DQS. In write states, the FPGA drives DQS as well as  

some data bits which have a different timing relationship to the output DQS. 


During writes, I have the data bits being clocked out with a 0-degree clock, and the DQS line is being clocked out with a 90-degree version of the same clock. This helps center the data eye around the outgoing DQS clock. 


Here's what I've tried: 


# Input Constraints create_clock -name CLK_ddr_ldqs_INPUT -period $DDR_CLK_PERIOD create_clock -name virt_clk -period $DDR_CLK_PERIOD set_multicycle_path 0 -from virt_clk -to CLK_ddr_ldqs_INPUT set_input_delay -clock virt_clk $tDQSQ -max set_input_delay -clock virt_clk -$tQHmin -min set_input_delay -clock virt_clk $tDQSQ -max -clock_fall -add_delay set_input_delay -clock virt_clk -$tQHmin -min -clock_fall -add_delay # Output Constraints set CLK_ddr_ldqs_n_OUTL CLK_ddr_ldqs_INPUT; set_output_delay -clock $CLK_ddr_ldqs_n_OUTL $tDS -max set_output_delay -clock $CLK_ddr_ldqs_n_OUTL -$tDH -min set_output_delay -clock $CLK_ddr_ldqs_n_OUTL $tDS -max -clock_fall -add_delay set_output_delay -clock $CLK_ddr_ldqs_n_OUTL -$tDH -min -clock_fall -add_delay  


The problem is, when I look at the timing path in TimeQuest, I see the output path:  


From Node: inst5|altpll_component|auto_generated|pll1|clk[0] 

To Node: ddr_dq[12] 

Launch Clock: inst5|altpll_component|auto_generated|pll1|clk[0] 

Latch Clock: CLK_ddr_udqs_INPUT 


(clk[0] is the 0-degree clock) 


but in the "Waveform" viewer, it is showing that the Launch clock and Latch clock are the same (there is no 90-degree phase shift). 


i tried replacing set CLK_ddr_ldqs_n_OUTL CLK_ddr_ldqs_INPUT; with : create_generated_clock -name CLK_ddr_ldqs_n_OUTL -source { inst5|altpll_component|auto_generated|pll1|clk }  


(clk[3] is the 90-degree clock) 


But I get the warning: Warning (332049): Ignored create_generated_clock at DDRCtrlTimingConstraints.sdc(327): Incorrect assignment for clock. Source node: ddr_ldqs_n already has a clock(s) assigned to it. Use the -add option to assign multiple clocks to this node. Clock was not created or updated. 


which ultimately leads to an error Error (332000): can't read "CLK_ddr_ldqs_n_OUTL": no such variable.  


I tried doing what it said and adding the "-add" flag. While this does get rid of the warning, it still doesn't get rid of the error. 


What's the right move here?
0 Kudos
5 Replies
Honored Contributor II

What's the multicycle of 0 for? That only gets used on the output in the edge-aligned case to account for data capture at the "downstream" device. 


Do you have a derive_pll_clocks somewhere that you're not showing here? That's why you would get the error about multiple clocks on the same node. 


Your generated clock on the output looks correct. My guess is you're using derive_pll_clocks, creating double clocks, causing the warning and error. Generate a clock report in the timing analyzer to see what clocks have been created by your sdc. 


See this online training for details on constraining a DDR source synchronous interface:
Honored Contributor II

The multicycle path 0 was because, in my understanding, the input pin was both the launch clock and the latch clock, as opposed to there being a "data was launched on the previous clock cycle, latched on the next clock cycle." This might be unnecessary, or an alternate way of doing this, or (most likely) I'm just super confused. 


I do have derive_pll_clocks defined. You say that "your generated clock on the output looks correct.", but I'm seeing a 0-degree phase in TimeQuest (see attached).  


I would expect to see the launch clock at 0 degrees, and the latch clock at 90 degrees based on how I've design the dq vs dqs timing. 


So either my constraints are wrong, or how I'm interpreting the the timequest waveform is wrong.
Honored Contributor II

I'm not sure if this helps or not, but attached is a diagram of the bidirectional signals and clocks. 


I've tried to color code the signals to help see which registers are involved during reads and which are involved during writes.
Honored Contributor II

As an experiment, I removed all statements related to input constraints, and just focused on the output constraints: 


create_generated_clock -name CLK_ddr_ldqs_OUTPUT -source { inst5|altpll_component|auto_generated|pll1|clk } set CLK_ddr_ldqs_n_OUTL CLK_ddr_ldqs_OUTPUT; set_output_delay -clock $CLK_ddr_ldqs_n_OUTL $tDS -max set_output_delay -clock $CLK_ddr_ldqs_n_OUTL -$tDH -min set_output_delay -clock $CLK_ddr_ldqs_n_OUTL $tDS -max -clock_fall -add_delay set_output_delay -clock $CLK_ddr_ldqs_n_OUTL -$tDH -min -clock_fall -add_delay 


Now, the timequest looks as I'd expect (attached). 


So obviously the SDC needs this "create_generated_clock" statement. To prevent the compiler from complaining, I had to remove the "create_clock" statement from the input portion. Is there a way to keep both? sstrell mentioned not having derive_pll_clocks? What would my constraints need to look like?
Honored Contributor II

Clocks that you need: 


input side: virtual clock (clock that drives the data from "upstream" device; use create_clock with no target), base clock (clock that arrives at FPGA from upstream device; use create_clock), PLL-generated clock that captures the data (from derive_pll_clocks) 

output side: PLL-generated clock that launches the data (from derive_pll_clocks), generated clock targeted at clock output port and sourced from PLL (relationship to source is -multiply_by 1) 


I never said to not use derive_pll_clocks. You just need to use it along with the other clock constraints I've listed. 


You don't want or need the multicycle. On the input side, the problem is you're missing the virtual clock. 


You also need set_false_path timing exceptions to prevent the timing analyzer from performing analysis that is not relevant to your design. I'm guessing you want center-aligned, same edge analysis (launch on rising edge, latch on rising edge; fall to fall too), so you would have set_false_path exceptions that prevent rise to fall and fall to rise analysis. 


Again, check out the online training. It spells all of this out.