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
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
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
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
--- 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
That makes sense. So from now on, the entire design uses statements like
if nRESET_sync = '0' then ---do stuff Right? - Altera_Forum
Honored Contributor
--- Quote Start --- Could you provide an example? --- Quote End --- Sure, you use the same component, with a slightly different connection:
So how does this work? Well, when nRESET is low (active), the registers internal to this synchronizer are immediately cleared and output '0', i.e., the nRESET_sync signal is asynchronously asserted. When nRESET is high (deasserted), the synchronizer chain starts to synchronize the input d, which in this case is a '1'. After a couple of clocks, the '1' appears at the synchronizer output, and viola, the nRESET_sync signal deasserts synchronously. Cheers, Davesync1 : sync generic map( RESET_STATE => '0' ) port map( clk => clk, rstN => nRESET, d => '1', q => nRESET_sync ); - Altera_Forum
Honored Contributor
--- Quote Start --- You should run reset through a reset synchronizer, i.e., a synchronizer that asserts reset asynchronously, but deasserts it synchronously, and then apply a false path. The reset and recovery time for the registers internal to the design will then be analyzed with respect to the synchronous deassertion of the reset signal. Cheers, Dave --- Quote End --- Could you provide an example? At the moment, I'm syncing signals like this:
I also read up on your byteblaster example but I don't think that implements a reset synchronizer.sync1 : sync generic map( RESET_STATE => '0' ) port map( clk => clk, rstN => nRESET, d => sck, q => SCK_sync ); - Altera_Forum
Honored Contributor
--- Quote Start --- why are we setting the synced signals as False Paths? Why do they not need a timing analysis? --- Quote End --- They are asynchronous signals, and you expect metastable states on those signals, right? That is why you have put a synchronizer on those signals. A timing analysis of those asynchronous inputs is meaningless, since the timing of a transition on the input is completely arbitrary with respect to the clock used by your FPGA logic. Once you have synchronized that signal, it is synchronized to the FPGA clock, and the FPGA clock constraint takes over. --- Quote Start --- One more question, what do I do with RESET? Is that also a false path? The RESET goes to a lot input paths it seems. --- Quote End --- You should run reset through a reset synchronizer, i.e., a synchronizer that asserts reset asynchronously, but deasserts it synchronously, and then apply a false path. The reset and recovery time for the registers internal to the design will then be analyzed with respect to the synchronous deassertion of the reset signal. Cheers, Dave - Altera_Forum
Honored Contributor
Thanks, I found what I did wrong with the Set False Paths step - I put in the path backwards! Also, why are we setting the synced signals as False Paths? Why do they not need a timing analysis?
One more question, what do I do with RESET? Is that also a false path? The RESET goes to a lot input paths it seems. - Altera_Forum
Honored Contributor
--- Quote Start --- 1) I went and created a clock of time period 50 ns (20 Mhz) and assigned the port to CLK. I named this SYSTEM_CLOCK. 2) I then went to the Set Output Delay dialog box and entered a delay of 2 ns. I chose SYSTEM_CLOCK as the clock and chose my 72 outputs. 3) I went into the Contraints menu and chose "Set False Paths". In the FROM field I put in SYSTEM_CLOCK and in the TO field I put in SCK. I did this again for CS and MOSI. I don't think I did this step quite right because in the reports I'm still told that I have 4 unconstrained inputs. Where do I tell TimeQuest that these are False Paths? --- Quote End --- If you are creating new constraints, then you have to re-run the analysis. Personally I create the .sdc file directly, and only use the GUI for analyzing the timing. --- Quote Start --- 5) I found the clock to output delay for my outputs. Do I just use these for my other design which has 72 inputs? Will 17.968 ~= 20 ns become the input delay? --- Quote End --- I forget whether you enter them directly, or indirectly via a calculated input delay, that is why I wrote the other tutorial. Read it. The answer should be in there :) Cheers, Dave