Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

SPI Master Timing Constraints

I know there is a lot of discussion on this board regarding timing constraints, but I couldn't find this topic well addressed.

I have a system where my FPGA interfaces to an ADC using a SPI like master interface. I am struggling a bit with how to properly constrain this IO. For the purposes of this discussion assume the interface contains SCLK (out), CS(out), MOSI(out), MISO(in). I think that I understand that the CS and MOSI signals should be treated as source synchronous signals with respect to SCLK for setup and hold analysis. However I am struggling a bit with how the MISO input should be treated. I know that I need to create a virtual clock to launch this signal with my latch clock being the internal SCLK.

To further complicate things, my setup contains several buffer stages for reasons I won't go into here that have potential for introducing skew between signals.

I have attached a diagram of my basic setup.

https://www.alteraforum.com/forum/attachment.php?attachmentid=6628

This is what I have so far in my SDC:

# base clocks

create_clock -name data_clk -period "32.768Mhz";# main clock

create_clock -name data_io_clk -period "32.768Mhz";# latch clock for MOSI and CS

create_clock -name data_io_clk_ext -period "32.768Mhz";# virtual clock for launch of MISO

derive_pll_clocks

derive_clock_uncertainty# ------------------------------------------------------------------------------# Component timing parameters# ------------------------------------------------------------------------------# ISO_BUF

set iso_buf_tsk 6.5

# CLK_BUF

set clk_buf_tsk 0.05

set clk_buf_tpd_min 0.8

set clk_buf_tpd_max 2.0

# DAT_BUF

set dat_buf_tsk 1.0

set dat_buf_tpd_min 1.5

set dat_buf1_tpd_max 5.1

# ADC

set adc_tsu 5.0

set adc_th 5.0

set adc_cto_min 10.0

set adc_cto_max 25.0# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------# FPGA <-> ADC SPI Interface Constraints# ------------------------------------------------------------------------------

set adc_in_min [expr $adc_cto_min]

set adc_in_max [expr $adc_cto_max]

set adc_out_min [expr -($clk_buf_tsk + $iso_buf_tsk + ($clk_buf_tpd_max - $dat_buf_tpd_min) + $adc_th)]

set adc_out_max [expr $clk_buf_tsk + $iso_buf_tsk + ($dat_buf_tpd_max - $clk_buf_tpd_min) + $adc_tsu]

set_input_delay -min -clock { data_io_clk_ext } $adc_in_min [get_ports adc_miso\[*\]]

set_input_delay -max -clock { data_io_clk_ext } $adc_in_max [get_ports adc_miso\[*\]]

set_output_delay -min -clock { data_io_clk } $adc_out_min [get_ports { adc_cs

adc_mosi\[*\]}]

set_output_delay -min -clock { data_io_clk } $adc_out_min [get_ports { adc_cs

adc_mosi\[*\]}]# ------------------------------------------------------------------------------

My basic strategy here was to analyze these signals for skew only as board delays will be basically negligible due to the fact that these signals begin routed together as a group. So my main concern is that I meet tsu and thd of the adc and that the miso meets tsu and thd of the FPGA. The overall tpd will be more then one clock cycle, but I can handle that in logic using delay states.

I am assuming I need to somehow account for the skew that would occur on the clock signal for the MISO signal, but I am having trouble understanding what this might look like.

Also for my outputs, when I compile this code and look at it in timequest, the tco of the FPGA is ~10ns, but when I actually run this configuration on hardware, the tco looks more like 5ns. In order to adjust for the potential skew introduced by the system my minimum tco needs to be greater then 12.05ns (adc_out_min) and my maximum tco must be less then 15.85ns. Anyone have any idea what I am doing wrong here and what I should change to achieve this?

Thanks in advance!

3 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Your clock constraints look incorrect; you're just creating 3 identical virtual clocks.

    Instead, you should do it like this:

    create_clock -name clk -period $mainClockPeriod [get_ports clk# Constrain the clock that actually goes into the FPGA

    derive_pll_clocks# Constrain PLL generated clocks

    create_generated_clock -name data_io_clk -source $pllOutput [get_ports $sclkOutputPortName]# Create a derived clock on the SCLK output pin

    You don't need a virtual clock for this case, because the clock is provided by the FPGA. So the CS, MOSI and MISO signals should all be constrained in relation to data_io_clk.

    What you need to do for MISO is the same thing you did CS/MOSI: take into account all your clock/signal buffers and the ADC's MISO tCO and figure out what's the minimum and maximum delay between a SCLK rising edge and a MISO transition, seen at the FPGA pins.

    In case of doubt, drawing the timing diagram always helps.

    Your output delay calculations look a bit more complicated than they should, but I didn't examine it carefully so they may be all right.

    It should be something like

    max output delay = adc tSU + sum of all max buffer delays on data path - sum of all min buffer delays on clock path

    min output delay = -adc tH + sum of all min buffer delays on data path - sum of all max buffer delays on clock path

    For the input delay, it should be

    max input delay = max adc tCO + sum of all max buffer delays on data path + sum of all max buffer delays on clock path

    min input delay = min adc tCO + sum of all min buffer delays on data path + sum of all min buffer delays on clock path

    You mention that your delays are > 1 clock and you'll use delay states to handle this. This is OK, but you may need to add multi-cycle exceptions to adjust the constrains, or TimeQuest may never give you a "pass" (even if your design might actually work).

    That said, I'm not sure you'll be able to achieve timing closure for 32 MHz operation, given all those delays.. you may have to run with a slower SCLK.

    I'll leave your last question to when you've fixed these issues. :)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thank you very much, this was very helpful. I too am very concerned about closing timing.

    After going through the exercise I think I have found that while I can close timing on the output signals interface, it will not be possible to close timing on the MISO using the current hardware approach. However, I do need to run at these speeds. I think I have come up with a method to allow this. If I loop back the SCLK and the CSn, that should set up a source synchronous interface for the MISO. If I then feed that SCLK into a PLL and phase shift as needed to center in the valid data window I should be able to both run at my desired speed and meet timing. Then for timing purposes, I only need to be concerned with the possible skew between signals similar to the what I was able to do for the output signals.

    Any thoughts on this approach?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I don't see anything wrong with nor do I have a better idea now. :)

    You might not need a PLL though, just using the falling edge of the received SCLK might work.

    Note that you'll have to treat the incoming SCLK as an asynchronous clock, in regard to SCLK and others.

    What are the values you got for min and max input delay?