Forum Discussion
Altera_Forum
Honored Contributor
14 years agoHow to constraint my design using TimeQuest?
I am looking for some help to constrain my design. I've never done a timing constraint and my understanding of the subject isn't very deep at all.
An overview of my design: it consists of a 72 bit shift register which is loaded in parallel (so that's 72 inputs). This data, when requested, is sent out via SPI. The SPI interface consists of MISO, MOSI, SCK (2 MHz) and CS. I sync. the SCK and CS signals to a 20 MHz clock (CLK) and shift out the data on the falling edge of the synchronized SCK signal (i.e. SCK_falling). Similarly, the chip is only active the synced copy of CS goes low (CS_falling). When CS_rising is 1, I load the data into the 72 bit shift register. Now, my question is, how do I properly constrain this design so it works on a real design? From my limited understanding, it seems I need to first create two clocks (SCK and CLK). I note that TimeQuest asks for the rising and falling times of the signal. Do I simply measure this on my board and enter it? In my case, I actually remember this: the rising/falling time for SCK is just 7 ns. However, for CLK it's a bit more tricky. My o-scope is only 50 MHz and the 20 MHz waveform appears quite distorted so it will be hard to measure the rise/fall times - can I just leave them out? Secondly, do I need to constraint the 72 inputs? If so, how? What about CS, MISO and MOSI? None of these have a set frequency as CS can go low and high at any time. So how does one go about constraining these?34 Replies
- Altera_Forum
Honored Contributor
--- Quote Start --- So from now on, the entire design uses statements like if nRESET_sync = '0' then ---do stuff Right? --- Quote End --- Essentially. However, its much easier to design your logic as components. In the top-level of the design you instantiate the reset synchronizer component and connect the synchronized output to the reset in your design. If you name your top-level reset differently than the reset port on your components, then you can do something like:
Cheers, Dave-- Synchronized reset signal rstN : std_logic; ... u1: sync ... d => ext_rstN, q => rstN ... u2: mydesign ... rstN => rstN, ... - Altera_Forum
Honored Contributor
Ah yes, I'll definitely do that. As a further question, I've fixed almost all the timing constraints in my design except this:
DO <= out_reg(out_reg'high) when nCS = '0' else 'Z'; This is a combinational one and so I'm kind of confused. I think I use the set max delay and set min delay for these? If I set set max delay to 20 and set min delay to 5, I get a setup time violation and Im not sure why. But if I only specify the max delay, I get no violations but im told that DO is only partially constrained. Another path that's unconstrained is out_reg[7] to DO. I assume that's also fixed by setting min/max delays? All of this is so confusing and none of the books I've read cover timing constraints and even if I somehow fix something in the SDC file, I feel like I don't know what I'm doing! EDIT: Using Set Output Delay fixed the issue! Now I only have to figure out how to tell TimeQuest that the 72 inputs will have a clock to output delay of 20 ns. - Altera_Forum
Honored Contributor
The other FPGA's clock to output delay will becomes (part of) this FPGA's input delay.
So, you probably want something like set_input_delay -clock SYSTEM_CLOCK -max 20 [get_ports my_inputs[*]] set_input_delay -clock SYSTEM_CLOCK -min XX [get_ports my_inputs[*]] You can get the XX value from the minimum clock to output delay report. Translation: this would be telling TimeQuest that the signal will reach the FPGA pins XX to 20 ns after the rising edge of SYSTEM_CLOCK. - Altera_Forum
Honored Contributor
Thanks
Here's my SDC file for the Parallel In Shift Out design:
I still have a couple of questions: I actually had the design working on a real board and I didn't really "bother" with the timings before this because the design worked at a low speed (500 KHz SPI bus with an 8 MHz oscillator. I was also unaware how critical they were.). However, I now have the deign working at 2 MHz (with a 20 MHz clock) and a seemingly random bug starts popping up: As mentioned, I use SPI to transfer data from the CPLD back to the MCU (the CPLD can also be on a different board but is always connected via a short wire and also has a series resistance to slow down the rising/falling edges). Yesterday, when I had the board running without proper constraints, I had rather frequent incorrect data transfers. One in 20 data transfers would fail (I know they'd fail because I compare the data against a stored array of bytes in an EEPROM). However, after some help from this thread and reading Altera's tutorial I set up the timings as shown in the above code. I reprogrammed all the CPLDs and the issue is MUCH MUCH less frequent but unfortunately still happens. Before, one in 20 data transfers would be bad. Now, one in 10,000 are bad. My question is, could timings still be behind this? Because I set up the timings the first time I'm not sure I did it correctly. For instance, the 15 ns delay for SO in the above code was something I guessed at random. How do I properly determine this? The MCU details it's setup and hold timings for SPI as 10 ns (typical). Should the output delay for SO be less or more than this? The min and max delays for PI[*] I got from my 'other design' which listed the max. clock to output delay as 19 ns and min. clock output delay as 9 ns. Are my values of 25 and 10 reasonable? I suppose my question really is that, basically, how do I find out what values to set for input and output delays? If you folks feel that timings aren't behind this than perhaps I should shift to LVDS instead of relying on SPI to transfer data over a 5 inch ribbon cable. I would massively appreciate any advice on this.create_clock -name sys_clk -period 50 set_false_path -from -to set_false_path -from -to set_false_path -from -to set_input_delay -clock { sys_clk } -max 25 }] set_input_delay -clock { sys_clk } -min 10 }] set_output_delay -clock { sys_clk } 15 - Altera_Forum
Honored Contributor
1) Doesn't your Parallel-in, Shift-Out design have more ports than those?
2) You should set a max output delay and a min output delay on SO. The max value will include the MCUs tSetup, while the min value will include the MCUs tHold. They should also include an estimate of wire delay and an estimate of clock to data skew. max output delay = tSetup + maxWireDelay + worseClockSkew min output delay = -Hold + minWireDelay - worseClockSkew And isn't your MCU capturing SO using the 2 MHz SCK? If so, you should constrain SCK and constraint SO in relation to SCK. 3) They look reasonable. But again max input delay = tCO + maxWireDelay + worseClockSkew min input delay = tCO_min + minWireDelay - worseClockSkew - Altera_Forum
Honored Contributor
Thank you for taking out the time to reply. The Parallel-in Shift Out design has the following ports:
CLK, SO/MISO, SCK, CS, nRESET and PI[72] Regarding (2): The MCU is a AT Mega 1281 and the data sheet specifies only typical values for the SPI interface. It lists tSetup and tHold as 10 ns. How would I go about estimating wire delay and clock skew? Here's the table that lists the tSetup and tHold: http://i.imgur.com/KWPlG.png The MCU is the master and sets the SPI bus speed, which is yes 2 MHz. However, SCK is synchronized with the CPLD's 20 MHz clock. If I understand your suggestion correctly, you're saying that I should declare SCK to also be a clock in the SDC file and constrain SO in relation to that? Even though I'm not directly using SCK, I sync the signal via two flip-flops and detect the rising falling edges of the synced signal. I then shift out the data onto SO based on the falling edge of the synced SCK signal. - Altera_Forum
Honored Contributor
Setting I/O constrains is all about describing to TimeQuest what's going on outside the FPGA.
Since the MCU is probably using SCK to sample SO, then that would be the way to go, if you want to apply an output constraint. But then again, I'd take a very different approach to this problem. I'd run my SPI interface logic on SCK, constraining SCK as a clock and constraining nCS and SO in relation to SCK. In the way you're doing it, using sys_clk to run the SPI interface logic, the best way may be to set a false path in SO as well. Since your 20 MHz clock is way faster than the 2 MHz SCK, you should be able to generate a SO signal which meets the MCUs timing requirements easily. 10 ns tHold => make sure you wait at least 1 clock (of sys_clk) between the rising of SCK and changing SO. 10 ns tSetup => make sure you wait less than 9 clocks between the rising of SCK and changing SO. - Altera_Forum
Honored Contributor
Regarding wire delay.
For PCB wire delay, I typically use 4-8 ps/mm. For cables.. depends on the cable. If I have it, I also tell TimeQuest the pin load capacitance, which it will use. But that assumes the load is mostly capacitive, with negligible resistance. Since you use Rs to slow down the slew, you have a RC load, which TimeQuest doesn't model. Either you calculate the effect of your RC load.. or you just measure the rise time in your scope and add that to your I/O delay. Regarding clock skew. The clocks in the two chips (sender and receiver) are not 100% in phase, due to wire delay between them (and clock buffers if you have them). If the sender's clock is a 5 ns ahead the receiver, then the receiver will get the data 5 ns earlier => subtract 5 ns to the delay If the sender's clock is a 5 ns behind the receiver, then the receiver will get the data 5 ns later => add 5 ns to the delay That said, the importance of precision in this estimates is relative. As long as your design isn't suffering from being over constrained, you can use rough but safe estimates. You're operating at low frequencies, you should have big timing margins. - Altera_Forum
Honored Contributor
--- Quote Start --- But then again, I'd take a very different approach to this problem. I'd run my SPI interface logic on SCK, constraining SCK as a clock and constraining nCS and SO in relation to SCK. --- Quote End --- It's interesting that you mention this as this was my initial approach. I had code like so:
However, from discussions here and other forums I was recommended to actually sample the SCK signal with a much faster clock so thats approach I took. I synchronize the SCK signal via two flop flops and then detect their falling and rising edges and do operations based on that. Here is my actual architecture in VHDL:if rising_edge(sck) then --do stuff
Based on your suggestion, I'll also set a false path for SO, like so:begin if (nRESET_sync = '0') then sck_rising <= '0'; sck_falling <= '0'; sck_delay <= '0'; elsif rising_edge(clk) then if cs_sync = '1' then sck_delay <= '0'; sck_rising <= '0'; sck_falling <= '0'; else sck_delay <= sck_sync; sck_rising <= sck_sync and (not sck_delay); sck_falling <= (not sck_sync) and sck_delay; end if; end if; end process; process(clk, nRESET_sync) begin if (nRESET_sync = '0') then cs_rising <= '0'; cs_falling <= '0'; cs_delay <= '0'; elsif rising_edge(clk) then cs_delay <= cs_sync; cs_rising <= cs_sync and (not cs_delay); cs_falling <= (not cs_sync) and cs_delay; end if; end process; process(CLK, nRESET_sync) begin if (nRESET_sync = '0') then tmp <= (others => '0'); elsif rising_edge(CLK) then if CS_sync = '0' then if SCK_falling = '1' then tmp <= tmp(PI'high -1 downto PI'low) & '0'; end if; elsif CS_sync = '1' then tmp <= PI; end if; end if; end process; SO <= tmp(PI'high) when nCS = '0' else 'Z';
Perhaps I should tell you more about the design regarding SO: SO is actually output with combinational logic:set_false_path -from -to
So SO depends upon nCS and tmp(PI'high) depends on the the synced version of the SCK signal (when it's falling, to be exact). Should I still go ahead and set this as a false path? Could you explain why I need to set this as a false path? I also didn't quite understand this bit: --- Quote Start --- Since your 20 MHz clock is way faster than the 2 MHz SCK, you should be able to generate a SO signal which meets the MCUs timing requirements easily. 10 ns tHold => make sure you wait at least 1 clock (of sys_clk) between the rising of SCK and changing SO. 10 ns tSetup => make sure you wait less than 9 clocks between the rising of SCK and changing SO. --- Quote End --- How do I ensure that I wait at least 1 clock cycle between the rising edge of SCK and SO? Do I set a delay for 10 ns for both mix/max? But I thought you said to set SO as a false path? Sorry if I'm way off the path here!SO <= tmp(PI'high) when nCS = '0' else 'Z'; - Altera_Forum
Honored Contributor
You set SO as a false path just so TimeQuest won't complain.
You ensure that you wait (at least) 1 clock cycle, not by setting constraints but by the working of your logic. In fact, you're already waiting 2 cycles (from the synchronizers) + 5 cycles (SCK falling) before changing tmp. I would just make SO depend on a synchronized/delayed version of nCS as well, to make sure SO doesn't go to Z too soon on the last bit.