3
\$\begingroup\$

I need to design an SPI slave peripheral inside an FPGA that shall be used to communicate with a Microcontroller and configure the behaviour of the FPGA design. I have a few questions.

  1. If the FPGA clock frequency is significantly higher than the input SCLK frequency, it is possible to sample the SCLK and detect the rising and falling edges. The design can use this information to shift or latch data. But, (a) What if the SCLK input clock is almost of same order as the FPGA system clock? Does the clock signal connect directly into the FPGA registers? (b) If not then what is the alternative?

  2. If (a) above is true then how do we write the timing constraints?

  3. The SCLK does not need to use global clock routing. Does this mean that any FPGA pin can be used for it?

\$\endgroup\$
5
  • \$\begingroup\$ The SPI bus version, MHz, and FPGA family would be useful to know. \$\endgroup\$
    – IanJ
    Mar 18, 2021 at 23:11
  • 1
    \$\begingroup\$ MCU's operating in target (vs host) mode typically re-sample the SPI clock. Peripheral chips without their own clock typically use it. You have to consider your needs; rarely would an SPI clock frequency challenge timing in a modern FPGA, so most of the issues would be in synchronization and crossing clock domains, not speed per se. \$\endgroup\$ Mar 19, 2021 at 16:32
  • \$\begingroup\$ OK so its like this, the SPI SCLK is 20MHz. There will be one slave select for FPGA and another for an ADC also configured by the uC. The FPGA clock frequency will be 33MHz. What can done in this case? The uC is a Renesas Synergy S124 series, the very low end one. The FPGA is an IGLOO2 M2GL025 or MAX10 (both will be tested). \$\endgroup\$
    – quantum231
    Mar 19, 2021 at 19:55
  • \$\begingroup\$ The IGLOO2 chip family has built in support for SPI bus. Top of page 20. microsemi.com/document-portal/doc_download/… \$\endgroup\$
    – IanJ
    Mar 20, 2021 at 0:16
  • \$\begingroup\$ There is a hardware SPI peripheral in the so called High Performance Memory Subsystem (HPMS) inside it. However, it is meant for one purpose alone, this is to load FPGA configuration bit stream by micrcontroller (or some other master device) through the SPI port. It is not meant for any other use. \$\endgroup\$
    – quantum231
    Mar 21, 2021 at 13:24

3 Answers 3

6
\$\begingroup\$

As soon as you introduce a SPI slave interface into your FPGA design, you introduce a new clock (the SPI clock) and a second clock domain. All of the SPI signals belong to that second domain, and you are now faced with the problem of reliably transferring information across the boundary. This is commonly referred to as "CDC" (clock domain crossing), and there's plenty of information about this topic if you search for it.

By far the most common approach, if the FPGA's main clock is fast enough, is to synchronize the three incoming signals (SSEL, SCLK, MOSI) into the main clock domain right away (two FFs per signal), run the SPI state machine in that clock domain, and ignore the jitter that this introduces into the output signal (MISO) feeding back into the SPI clock domain. This generally works fine.

An alternative approach is to run the SPI state machine in the SPI clock domain, and transfer information between the two clock domains a byte or word at a time using asynchronous (dual-clock) FIFOs. This approach can potentially run faster, but it requires careful design of the state machine that takes into account the limited number of clock edges available to it.

In either case, you will have one set of timing constraints for the FPGA clock domain, another set of constraints for the SPI clock domain, and a third set that covers the CDC.

\$\endgroup\$
3
  • \$\begingroup\$ Dave the SCLK feeds only a few registers inside the whole design. When we say "clock domain" it makes it sound like the SCLK will feed into one of the clock input pins and the be distributed across a portion of the FPGA as its sole clock signal. This implies that the whole portion of the FPGA (maybe a quarter that uses this clock routing) will be unuseable to to being locked into a single SPI clock domain. \$\endgroup\$
    – quantum231
    Mar 19, 2021 at 12:56
  • \$\begingroup\$ @quantum231, you have multiple clock distribution networks everywhere, otherwise the compiler would be very constrained when trying to lay out clock domain crossing logic -- so the SPI clock will be available to a large segment of the FPGA, but there is no requirement to use it. CPLDs are much more restricted there, and this would definitely be a concern here. \$\endgroup\$ Mar 19, 2021 at 13:00
  • 1
    \$\begingroup\$ @quantum231: A clock domain is a clock domain, no matter how big it is. You always need to deal with it and its CDCs properly. Sure, sometimes you can use strictly local routing resources, and sometimes it's just as convenient to use a global resource. But that's just an implementation detail. \$\endgroup\$
    – Dave Tweed
    Mar 19, 2021 at 14:01
3
\$\begingroup\$

If the FPGA clock is >= 4X the SPI clock rate it is relatively easy to digitally detect the edges. Nyquist says you only need 2X, but its really hard to guarantee that you'll see all the edges. If they are almost the same speed you should use the SCLK. It should go through the FPGA clock buffers so that you will have a low amount of clock skew. There are clock conditioners / PLLs that will let you take in the SCLK and adjust the phase so that you can drive it to the Flip-Flops in the I/O registers.

Writing timing constraints is one of the hardest parts of FPGA design. You need to look at the SPI spec and also account for board routing delays. If you define the phase relationship between the data and the clock at the IO pin, the tools will let you know if it will meet timing at the flip-flops.

You may not need global clock routing, but I would recommend at least regional clock routing. If you use certain pins on some FPGAs it can be routed to clock buffers more easily.

\$\endgroup\$
0
\$\begingroup\$

The solution will depend on the requirements of your design. I have been implementing SPI slaves often in FPGAs. These are usually used to implement a register interface for an external CPU to control and monitor functions inside the FPGA.

I generally use the SPI clock as intended, and implement a shift-register in the SPI clock domain. This circuitry interfaces to the FPGA main clock domain where the shift register data is transferred (in parallel) to or from the FPGA clock domain. Care must be taken to ensure timing is met across this boundary. There are many options here: multicycle delay, dual-port ram (FIFO) are two of them. SPI is really a very low-level specification. The intent is that you can implement a rudimentary SPI slave with very few resources (in the limit, this could be a few flip flops). There is lots of flexibility to implement your own protocol on top of the basics.

\$\endgroup\$
3
  • \$\begingroup\$ See, it is trivial to connect SCLK into the clock signal of some registers. The bigger question is, what is the correct way to make such an SPI slave? Do we use dedicated clock pin for SCLK and if we do so, that will mean that a lot of registers will be fed from that clock. Isn't that a problem? Also, how to constrain the design? I guess we can just add a false path for clock domain crossing side specifically. \$\endgroup\$
    – quantum231
    Mar 19, 2021 at 19:59
  • \$\begingroup\$ It is not necessary to use a global clock for SPI SCLK. The FPGA tools can deal with timing closure either way (global or not). Personally, I let the vendor tools decide which clocks to assign as globals. Global really means that there is a dedicated routing network for the clock and has favorable timing characteristics compared to general purpose routing. A global clock still only goes to the registers that need it. The dedicated clock pin, provides the best possible clock performance when used for a global clock. It is good to use this for high performance clock needs.(usually SPI is not) \$\endgroup\$
    – Troutdog
    Mar 21, 2021 at 0:55
  • \$\begingroup\$ The way I handle the clock crossing is functionally: I make sure the SPI side is stable before sampling that data into the other clock domain. This means defining the functional timing for the interface, and making sure, through design, that timing will be met. You cannot get a clock crossing to work through constraints alone since you cannot predict the relationship between 2 independent clock domains. Boiling it down, you have to stabilize the data on one side long enough to guarantee you can sample it reliably on the other. \$\endgroup\$
    – Troutdog
    Mar 21, 2021 at 1:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.