Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21584 Discussions

SPI Master Timing Constraints

Altera_Forum
Honored Contributor II
7,962 Views

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!
0 Kudos
3 Replies
Altera_Forum
Honored Contributor II
6,167 Views

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. :)
0 Kudos
Altera_Forum
Honored Contributor II
6,167 Views

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?
0 Kudos
Altera_Forum
Honored Contributor II
6,167 Views

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?
0 Kudos
Reply