UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor muggi
Visitor
15,773 Views
Registered: ‎03-17-2009

Sample SPI clock on FPGA

Jump to solution

Hi,

 

I am trying to implement my own custom SPI connection between two Virtex 5 FPGA evaluationboards, but I have some problems sampling the SPI clock.

 

My SPI clock is 12.5 MHz and it is sampled by the sys_clk (125 MHz), so I guess this is not a problem. 

 

At first I tried to sample the SPI clock by  delaying the SPI clk by one sysclk and route it in to another process where I compare the current and the delayed SPI clk.

 

If the current SPIclk = 1

and the delayed SPIclk =  0

 

the process generated a output signal (sclk_event = 1) symbolizing a positive SPIclk edge.

 

However this resulted in a rather unstable sampling of the SPIclk,as it was only sampled about 80% of the times it was supposed to

 

 

 

Next i tried to sample the SPIclk in a two bit **bleep** register and then wait for the registervalue to be "01" to generate the output (sclk_event)

 

All of the sudden the sampling of the SPIclk is all stabil.

 

 

Does anyone know why the first way of sampling the SPIclk does not work?

 

while I got your attention, does anyone know if my 12,5 MHz SPIclk needs to be routed on some sort of clock deticated I/O pin?

 

 

 

here is my VHDL examples:

First the two processes, one delay process and one SPIclk event generate process:

 

entity Delay_one_clock is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           d_in : in  STD_LOGIC;
           d_out : out  STD_LOGIC);
end Delay_one_clock;

architecture Behavioral of Delay_one_clock is

begin

pass_on : process( clk, rst ) is
   
   
    begin
        if (rst='1') then

            d_out <= '0';
           
        elsif (clk'event and clk = '1') then

            d_out <= d_in;

        end if;
     
    end process pass_on;

end Behavioral;

 

=======================================================

 

 entity Generate_Sclk_event is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           sclk : in  STD_LOGIC;
           delayed_sclk : in  STD_LOGIC;
           sclk_event : out  STD_LOGIC);
end Generate_Sclk_event;

architecture Behavioral of Generate_Sclk_event is

begin

    Genrate_clk_event : process( clk, rst ) is
    begin
    
        if (rst='1') then

                sclk_event <= '0';
               
        elsif rising_edge(clk) then        
        
            -- if sclk rising_edge

            if (sclk = '1' and delayed_sclk = '0') then
           
                sclk_event <= '1';
               
            else
           
               sclk_event <= '0';
               
           end if;
            
        end if;
    
    end process;

end Behavioral;

 

=========================================================

 

Then the process with the shif register:

 

 

 entity Generate_Sclk_event is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           sclk : in  STD_LOGIC;
           sclk_event : out  STD_LOGIC);
end Generate_Sclk_event;

architecture Behavioral of Generate_Sclk_event is

    signal Sclk_samples : STD_LOGIC_VECTOR(1 downto 0);

begin

    Genrate_clk_event : process( clk, rst ) is
    begin
    
        if (rst='1') then

                sclk_event <= '0';
                Sclk_samples <= "00";
                
        elsif rising_edge(clk) then
        
            Sclk_samples(1) <= sclk_samples(0);
            Sclk_samples(0) <= sclk;
            
        
            -- if sclk rising_edge
            if(Sclk_samples = "01") then
            
                sclk_event <= '1';
                
            else
            
                sclk_event <= '0';
                
            end if;
           
        end if;
    
    end process;

end Behavioral;

 

 

 

 

 

 

Any help i appriciated 

 

Muggi

 

 

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
Observer bialken
Observer
20,294 Views
Registered: ‎11-24-2008

Re: Sample SPI clock on FPGA

Jump to solution

Probably not.

 

If your SPI interface is like others I've seen, data changes on one edge and is sampled with the other. As such, the data is stable around the sampling edge. In particular, it's been stable for a whole long time - 5 125 MHz clocks (40 ns) - well long enough to prevent violation of the setup/hold times of the input flip-flop.

 

Because you (probably) only sample the data and the slave select at a SPI clock edge, they're only sampled when the data is stable. This is good. The clock is the exception though - you're sampling it constantly, so it needs to go through a synchronizer.

 

Incidentally, synchronizing multiple bits of a bus is a good way to cause occasional bit errors. Synchronizers are probabilistic device. If you have two of them sampling two bits that are changing together, there's a chance the output of one synchronizer may be 1 bit ahead of the other. The easy way to fix this is only to synchronize one bit - specifically a clock or a data enable, and then use that synchronized control signal to sample the rest of the bits.

0 Kudos
6 Replies
Observer bialken
Observer
15,761 Views
Registered: ‎11-24-2008

Re: Sample SPI clock on FPGA

Jump to solution

The fact that your SPI clock frequency is much less than your system clock frequency in no way makes it "safe" to sample it directly in the system clock domain. If the SPI clock is being generated by an oscillator that is in any way different from your system clock (even if they are the same frequency), the SPI clock is asynchronous to your system clock oscillator. As such, it will occasionally violate the setup or hold time requirements of the input flip-flop on the FPGA, causing that flip-flop to go metastable for a certain (albeit short) amount of time. This fact is the source of quite a few FPGA problems.

 

The solution is fortunately quite simple. A synchronizer is a two bit shift register that reduces the chances of a metastable output to a statistically insignificant figure. If you put the SPI clock through a synchronizer and then edge detect it, there's essentially no chance your edge detection circuit will be "looking at" a metastable output.

0 Kudos
Visitor muggi
Visitor
15,726 Views
Registered: ‎03-17-2009

Re: Sample SPI clock on FPGA

Jump to solution

Thanks for your help,

 

Am I right when I assume that the shift register in my second solution will work as a synchronizer?

0 Kudos
Observer bialken
Observer
15,703 Views
Registered: ‎11-24-2008

Re: Sample SPI clock on FPGA

Jump to solution
Technically, you're not putting the SPI clock through a synchronizer in the second solution. There's only one register between the input and where you use the signal. You can often-times get away with that with a "slow" clock and a "fast" FPGA, but it's not good design practice and can vary build to build. I would suggest you make Sclk_samples a 3 bit vector and then compare only the most significant two bits.
0 Kudos
Highlighted
Visitor muggi
Visitor
15,676 Views
Registered: ‎03-17-2009

Re: Sample SPI clock on FPGA

Jump to solution

Thanks a lot,

 

I have seen examples using a 3 bit vector in stead of a 2 bit... Now I know why!

 

When I come to think about i it, I guess I have to use a synchronizer on my data signals and my chip select signal, right?

 

0 Kudos
Observer bialken
Observer
20,295 Views
Registered: ‎11-24-2008

Re: Sample SPI clock on FPGA

Jump to solution

Probably not.

 

If your SPI interface is like others I've seen, data changes on one edge and is sampled with the other. As such, the data is stable around the sampling edge. In particular, it's been stable for a whole long time - 5 125 MHz clocks (40 ns) - well long enough to prevent violation of the setup/hold times of the input flip-flop.

 

Because you (probably) only sample the data and the slave select at a SPI clock edge, they're only sampled when the data is stable. This is good. The clock is the exception though - you're sampling it constantly, so it needs to go through a synchronizer.

 

Incidentally, synchronizing multiple bits of a bus is a good way to cause occasional bit errors. Synchronizers are probabilistic device. If you have two of them sampling two bits that are changing together, there's a chance the output of one synchronizer may be 1 bit ahead of the other. The easy way to fix this is only to synchronize one bit - specifically a clock or a data enable, and then use that synchronized control signal to sample the rest of the bits.

0 Kudos
Scholar ronnywebers
Scholar
7,822 Views
Registered: ‎10-10-2014

Re: Sample SPI clock on FPGA

Jump to solution

@bialken thanks for the great explanation. 2 questions if I may :

 

1) would it be good / ok to pass the incoming data line also through a 2-FF synchroniser, in order to keep the data timing better aligned with the clock that went also through a 2-FF synchroniser? I've read about possible issues when you try to synchronize parallel busses, but in this case data in is only a single signal.

 

2) I know there is a short-hand notation using a std_logic_vector to write a synchronizer in a compact way. Could you show an example maybe? 

 

3) where do you get the 5 clock cycles from (40ns), is this of a 3-stage synchronizer followed by 2-stage edge detector?

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos