# How fast should I clock my CPLD as compared to my SPI bus' speed?

As I'm sure everyone here knows, in FPGA/CPLD design one often needs to synchronize a slower asynchronous signal (say, the SCK line of SPI) with a much faster clock signal thats directly fed to the FPGA/CPLD. My question is, how much faster does the FPGA/CPLD clock needs to be relative to my asynchronous signal? Ten times? Twenty times?

In my case less than 10x doesn't work well. Specifically: I set my SCK speed to 4 MHz whereas my clock was 20 MHz. This didn't work at all. 2 Mhz works, but occasionally I get some problems. At 1 MHz, it works very well - no issues so far.

VHDL Code for the CPLD:

library ieee;
use ieee.std_logic_1164.all;

entity PISO is
port(CLK, nCS, SCK, nRESET : in std_logic;
PI  : in  std_logic_vector(71 downto 0);
SO  : out std_logic);
end PISO;

architecture archi of PISO is
signal tmp: std_logic_vector(PI'high downto PI'low);
signal bitOut: std_logic;
signal rise, fall : std_logic;
signal oscena:   std_logic;
signal iCLK  :   std_logic;

signal SCK_rising, SCK_falling, SCK_sync, SCK_delay : std_logic;
signal CS_rising, CS_falling, CS_sync, CS_delay     : std_logic;

component sync
generic(
RESET_STATE : std_logic := '0' -- '0' for active low sync
);
port(
clk  : in  std_logic;
rstN : in  std_logic;
d    : in  std_logic;
q    : out std_logic
);
end component;

begin
sync1 : sync
generic map(
RESET_STATE => '0'
)
port map(
clk  => clk,
rstN => nRESET,
d    => sck,
q    => SCK_sync
);

sync2 : sync
generic map(
RESET_STATE => '1'
)
port map(
clk  => clk,
rstN => nRESET,
d    => nCS,
q    => CS_sync
);

process(clk, nRESET)
begin
if (nRESET = '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)
begin
if (nRESET = '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)
begin
if (nRESET = '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';

end archi;


And here's the code for the sync component:

library ieee;
use ieee.std_logic_1164.all;

entity sync is
generic (
RESET_STATE : std_logic := '0' -- '0' for active low sync
);
port (
clk   : in  std_logic;
rstN  : in  std_logic;
d     : in  std_logic;
q     : out std_logic
);
end entity;

architecture behavioral of sync is
signal d_meta : std_logic;
begin
process(clk, rstN)
begin
if (rstN = '0') then
d_meta <= RESET_STATE;
q      <= RESET_STATE;
elsif (clk'event and clk = '1') then
d_meta <= d;
q      <= d_meta;
end if;
end process;
end architecture;


Regarding simplicity, I know SPI is super simple but I'm a newbie so all of this is rather difficult for me. Only after weeks did it make sense to me that I do need to sync. the signals in the CPLD/FPGA (initially I was just using the SCK as my clock and didn't even have a separate clock on my board. It worked fine for slower speeds but increasing the speed to even 1 MHz made the naiveness of my approach obvious). I'm sure (infact, I know because of your excellent posts around here) your approach is much simpler and more elegant, the issue is that I'll need to get my head around it first because as of now it just sounds like greek to me!

• What's the SCK's pulse width? – stevenvh May 30 '12 at 13:33
• @stevenvh By pulse width, I assume you mean the length of time where the SCK is high? I believe that's half of the time period, so about 0.25 uS if my math is right. I'll measure it tomorrow at work and update here. – Saad May 30 '12 at 13:40
• The reason I'm asking is that clock frequency isn't everything. If your clock is 1MHz that's 1us period. So sampling at 10MHz would give you 10 samples over that, ideally 5 high and 5 low. If your clock produces only narrow pulses, say 100ns, that may be perfectly within specs (probably, since you're allowed to clock it much faster), but you'll only have 1 sample at 10MHz. So there's a chance of missing that one. – stevenvh May 30 '12 at 13:44
• I'm not sure what's naive about using SCK as a clock inside the CPLD, unless it's something CPLD-specific. FPGAs can have multiple clock domains inside. Was the clock trace suffering from transmission-line reflections, or was it too slow, or something else? – ajs410 May 30 '12 at 20:37
• @ajs410 I was told that async. design is a Bad Thing in the FPGA/CPLD world and it's better if I sycned my signals with an external clock. – Saad May 30 '12 at 21:02

There are so many things in this question that it is difficult to know where to start.

I am assuming that your FPGA logic is a SPI slave, not a master. If it is a master then you have a whole different set of issues which I'm going to avoid going into right now.

The simple direct answer to your question is that you need to sample an async signal at least two times the frequency of your signal. So if you have a 4 MHz clock then you need to sample it at 8 MHz or higher. Of course, nothing is simple or direct in this case.

You have things a little more difficult because you are not sampling one async signal, you are sampling three (CLK, CS, and MOSI). You also need to keep those three signals time-aligned with each other through the sampling process. And you have to spit out MISO in such a way as to not violate your setup/hold time at the master.

None of this is easy, but having a higher speed clock will make things much easier. How much higher depends on your code, and you didn't post your code. I think that I could write code to do it with an 8x clock, but that is just a guess. Honestly, however, I think this is the wrong approach.

SPI is a super simple interface, and it would be good if you kept it super simple. SPI has its own clock, and if you use it as a clock then everything becomes almost easy. Instead of changing clock domains on the serial SPI interface, change clock domains on the parallel data going in/out of your shift registers. If you look at those signals carefully you might even realize that you don't need to do anything special, or if you do then it's just a flip-flop per signal. Then you don't need to have your main clock be higher than your SPI clock. Your main clock could actually be slower!

I do this on my SPI FPGA/CPLD interfaces and I have no problems running SPI at 30+ MHz, with or without a second clock domain.

• "at least two times the frequency of your signal". You know that this is not quite correct. I mention in comment a 100ns pulse width at a 1MHz clock. Sampling at 2MHz will likely miss the pulse. You need twice the harmonic required to have a decent signal, amplitude-wise, and edge-wise. – stevenvh May 30 '12 at 13:56
• @stevenvh True, but I wasn't going to worry about the details too much because I went on to say that for this application you probably need 8x, or better yet do something else entirely. – user3624 May 30 '12 at 14:21
• Or use hardware that will hold the pulse and has to be actively reset so you receive it? – Kortuk May 30 '12 at 14:25
• @Kortuk - That sounded like a good idea, but on second though, what if it clocks on the falling edge? That will have to be accurate. IIRC SPI clocks in and out at opposite edges. – stevenvh May 30 '12 at 14:58
• @stevenvh, or operate in opposite direction(reset sends line high, or just invert the signal for all it matters). I am just saying if there is a certain signal you are looking for something like this can help. – Kortuk May 30 '12 at 14:59

I would suggest that, if practical, an SPI slave should have registers that are clocked from the SPI pins. Those registers, or signals that derive from them, should then be double-synchronized with other logic. Depending upon application requirements, signals from the other logic may either be double synchronized to the SPI clock or may be fed to the SPI's data output asynchronously (if the SPI data is going to be fed to a single data path which contains at least two latches before it splits, and if the application won't care whether an attempt to read something at the moment it changes yields high or low, async reporting may be just fine).

Even if one doesn't want to design an entire SPI slave interface to be SPI-clocked, one can still have a few key aspects of it clocked from the SPI wires. At minimum, I would suggest that the SPI clock wire should trigger a latch for the data and a toggle latch. Pass the data latch through one more level of synchronization than the toggle latch, and then assume that any time the toggle latch value differs from the previous one, new data exists on the clock wire. Some extra latching logic on the chip-select wire would allow reliable detection of short unselect/reselect events.

PS--Depending upon how the logic and software protocol are designed, it may be possible to have an SPI slave device work reliably even if the attached logic likes to sleep when idle and doesn't wake up "instantly". Such behavior could not be implemented if everything on the SPI bus had to be synchronized to the main-logic clock (which wouldn't be running while the device was asleep).

• ...would there be a danger that the FPGA might rewrite things so that transitions on that signal when it wasn't supposed to matter might cause glitches downstream? For example, given the equation Q := (Q and not E) or (D and E) [D FF with enable] would there be a danger that a compiler might implement that using a non-hazard-free 3-input mux, such that a transition on D near the clock edge could glitch Q even when synchronous signal E was low? Is there any nice way to handle such things? – supercat Jul 17 '14 at 15:35