+ Post New Thread
Results 1 to 15 of 15
  1. #1
    Junior Member level 3
    Points: 150, Level: 1

    Join Date
    Oct 2018
    Posts
    29
    Helped
    0 / 0
    Points
    150
    Level
    1

    Propper clock generation for SPI protocol

    Hello.

    I want to implement the SPI protocol in VHDL over an FPGA.
    My question here is quite simple, I want an option in order to decide which frequency to use. For example, if I have a fast device as an screen an a slow device as a sensor I need to communicate them with different frequencies.
    As my FPGA works @50MHz I thought it would be a great idea to make a clock divider, so I would work with 50, 25, 10, 5, 2 and 1Mhz.

    How is the best way to implement them? I could define some values and count them, but I also can have 6 clocks at the same time.
    This last option would be something like this:

    Code:
    Process(CLK50) is
    	If(rising_edge(CLK50))then
    		CLK25<=NOT(CLK25)
    	End if;
    End Process;
    
    Process(CLK25) is
    	If(rising_edge(CLK25))then
    		CLK10<=NOT(CLK10)
    	End if;
    End Process;
    So I would have 6 process. I guess this is not the best option, but I'm not sure if generating clocks from counters is such a good idea.

    •   AltAdvertisment

        
       

  2. #2
    Super Moderator
    Points: 249,725, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    43,472
    Helped
    13213 / 13213
    Points
    249,725
    Level
    100

    Re: Propper clock generation for SPI protocol

    25/2 is hardly giving 10 MHz. Apart from this trivial calculation error, your ripple carry divider is about the worst method to generate a clock.

    You should consider a simple scheme with a single clock domain (e.g. 50 MHz) and clock enables of different speed generating the output signals. This means, no edge sensitive condition will use a different clock than 50 MHz.

    A general comment regarding your intention, it's rather unusual to switch SCK frequency of a SPI bus to serve devices with different speed capability. I presume it's not even permitted in the datasheets.



  3. #3
    Junior Member level 3
    Points: 150, Level: 1

    Join Date
    Oct 2018
    Posts
    29
    Helped
    0 / 0
    Points
    150
    Level
    1

    Re: Propper clock generation for SPI protocol

    Would something like this be correct or is there a better way? I ask because, in the other thread I opened, I had problems with clock generations, and I want to do it right this time.

    Code:
    	Clock25: process(CLK_50)
    	begin
    		if(rising_edge(CLK_50))then
    			if(en_Clk25='1')then
    				CLK_25<=NOT(CLK_25);
    			end if;
    		end if;
    	end process;
    	
    	Clock10: process(CLK_50)
    	begin
    		if(rising_edge(CLK_50))then
    			if(en_Clk10='1')then
    				if(count10<half10)then
    					CLK_10<='1';
    					count<=count+'1';
    				else
    					CLK_10<='1';
    					count<=count+'1';
    					if(count=max10)then
    						count<=(others => '0');
    					end if;
    				end if;
    			end if;
    		end if;
    	end process;
    	
    	Clock5: process(CLK_50)
    	begin
    		if(rising_edge(CLK_50))then
    			if(en_Clk5='1')then
    				if(count5<half5)then
    					CLK_5<='1';
    					count<=count+'1';
    				else
    					CLK_5<='1';
    					count<=count+'1';
    					if(count=max5)then
    						count<=(others => '0');
    					end if;
    				end if;
    			end if;
    		end if;
    	end process;



  4. #4
    Advanced Member level 5
    Points: 36,873, Level: 46
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,727
    Helped
    1963 / 1963
    Points
    36,873
    Level
    46

    Re: Propper clock generation for SPI protocol

    just ditch the idea of slower "clocks" altogether. You should ideally have a single system clock, and that is it. With SPI, the SCK is usually much slower than your system clock, so you can treat it as any other signal, and synchronise it to your system clock and do edge detection. Use this edge detection as a clock enable to your incoming data (also synchronised) registers.

    For outgoing data, again, just create clock enables. You have problems in your current code because you see to have the same idea of generating clocks (although CLK10 and CLK5 are always '1' and dont toggle), but they are generated from a clock enable. You should ditch these clock altogether, and generate clock enables:

    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    signal cnt          : unsigned(3 downto 0)  := (others => '0');
    signal en_1_in_16   : std_logic;
    signal en_1_in_2    : std_logic;
    signal en_1_in_8    : std_logic;
     
    process(clk)
    begin
      if rising_edge(clk) then   
        cnt         <= cnt + 1;
        
        -- Defaut enables to 0
        en_1_in_16  <= '0';
        en_1_in_2   <= '0';
        en_1_in_8   <= '0';
        
        if cnt = 0 then
          en_1_in_16  <= '1';
        end if;
        
        if cnt rem 2 = 0 then
          en_1_in_2   <= '1';
        end if;
        
        if cnt rem 8 = 0 then
          en_1_in_8   <= '1';
        end if;
      end if;
    end process;


    1 members found this post helpful.

    •   AltAdvertisment

        
       

  5. #5
    Junior Member level 3
    Points: 150, Level: 1

    Join Date
    Oct 2018
    Posts
    29
    Helped
    0 / 0
    Points
    150
    Level
    1

    Re: Propper clock generation for SPI protocol

    I have simulated the code you posted here and what I see are 3 signals:
    -Clock @50MHz
    -Clock2 @ 3.125MHz
    -Clock3 @ 6.25MHz

    Also I observe the duty cycle is not 50%. So I have some doubts maybe you can solve.
    Is a very elegant way of clock generation, but, can I use the same values I posted on my OP? Can i get a 50% duty-cycle?

    The main idea is to make a SPI protocol, so i must work with phase and polarity, will I be able to do it going that way?



    •   AltAdvertisment

        
       

  6. #6
    Advanced Member level 3
    Points: 5,683, Level: 17

    Join Date
    Feb 2015
    Posts
    939
    Helped
    269 / 269
    Points
    5,683
    Level
    17

    Re: Propper clock generation for SPI protocol

    I think the main challenge is the need to run the core at 50MHz with a 50MHz system clock and also lower rates.

    The general way to deal with this is some form of SIPO/PISO interface and/or frequency synthesis to avoid needing to have a process with a falling edge.



  7. #7
    Junior Member level 3
    Points: 150, Level: 1

    Join Date
    Oct 2018
    Posts
    29
    Helped
    0 / 0
    Points
    150
    Level
    1

    Re: Propper clock generation for SPI protocol

    I have created the clocks I wanted, but I still worried about the duty-cycle. As far as I know, I must use a 50% duty-cycle for SPI, no? Or at least bwtween 40-60%?

    Click image for larger version. 

Name:	Relojes.PNG 
Views:	4 
Size:	33.0 KB 
ID:	150249



  8. #8
    Super Moderator
    Points: 249,725, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    43,472
    Helped
    13213 / 13213
    Points
    249,725
    Level
    100

    Re: Propper clock generation for SPI protocol

    The signals shown in your simulation are clock enable signals, used to enable register transfers in the 50 MHz clock domain. They won't be used as SPI clocks and don't need symmetrical duty cycle. By design, the are always one system clock period wide.

    Instead consider a clock enable signal with double the intended SCK frequency, it can be used to toggle SCK in the active transmission phase, also set nCS and SDO and sample SDI in combination with the actual SCK phase.



  9. #9
    Junior Member level 3
    Points: 150, Level: 1

    Join Date
    Oct 2018
    Posts
    29
    Helped
    0 / 0
    Points
    150
    Level
    1

    Re: Propper clock generation for SPI protocol

    It seems that I still not understanding the "clock enable" concept you all talk me about. From the code TrickyDicky posted I have made the following one, which toggles and creates clock signals.
    Code:
    process(CLK_50)
    begin
    	if rising_edge(CLK_50) then   
    		cnt	<= cnt + 1;
    		--25MHz
    		if cnt rem 1 = 0 then
    			CLK_25   <= NOT(CLK_25);
    		end if;
    		--5MHz
    		if cnt rem 5 = 0 then
    			CLK_5   <= NOT(CLK_5);
    		end if;
    		--1MHz
    		if cnt rem 25 = 0 then
    			CLK_1   <= NOT(CLK_1);
    		end if;
    		--Reset
    		if(cnt>49)then
    			cnt<="000001";
    		end if;
    	end if;
    end process;
    Is it OK to use the generated clock signals as SCLK, or am I missing something?



  10. #10
    Full Member level 5
    Points: 2,017, Level: 10

    Join Date
    May 2014
    Posts
    243
    Helped
    23 / 23
    Points
    2,017
    Level
    10

    Re: Propper clock generation for SPI protocol

    When the division is not a multiple of 2, the duty cycle can be 50-50 with the following method; unless you have some sort of setup and hold time constraint the pulsed clock should be enough.

    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    architecture rtl of clk_divn is
     
        signal pos_count, neg_count : unsigned(count_size-1 downto 0);
     
    begin  
        pos_cnt_proc : process(clk_in) is
        begin
            if rising_edge(clk_in) then
                if rst='1' then
                    pos_count <= (others => '0');
                else
                    if pos_count = div-1 then 
                        pos_count <= (others => '0');
                    else 
                        pos_count <= pos_count + 1;
                    end if;
                end if;
            end if;
        end process;
        neg_cnt_proc : process(clk_in) is
        begin
            if falling_edge(clk_in) then
                if rst='1' then
                    neg_count <= (others => '0');
                else
                    if neg_count = div-1 then 
                        neg_count <= (others => '0');
                    else 
                        neg_count <= neg_count + 1;
                    end if;
                end if;
            end if;
        end process;
     
        clk_out <= '1' when (pos_count > (div/2)) OR (neg_count > (div/2)) else '0';
    end architecture rtl;



  11. #11
    Super Moderator
    Points: 67,586, Level: 63
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    13,823
    Helped
    3153 / 3153
    Points
    67,586
    Level
    63

    Re: Propper clock generation for SPI protocol

    Hi,

    your HDL skills are improving

    My question: Do you need all 3 clocks at the same time? Or do you need just one clock?

    Your approch seems to be OK. You generate "signals" but they are not "clock signals" in the meaning of FPGA system clocks (with their own clock distribution network).
    And yes you can use those (non clock) signals as SPI SCK.

    But donīt use this signals internally as clock for new signals like MOSI, MISO... [--> NOT: "if rising_edge(SCK) ..]
    *****

    I recommend to generate an SPI_Ena signal with twice the SCK frequency.

    always run a counter 0...n
    n= (50MHz / 2 / SCK_freq) -1
    n=0 for 25MHz
    n=4 for 5MHz
    n=24 for 1MHz


    Here some pseudo code:
    Code:
    process(CLK_50)
    begin
       if rising_edge(CLK_50) then   
          if cnt  >= n then
             SPI_Ena = 1 
             cnt = 0
          else
             SPI_Ena = 0
             cnt	<= cnt + 1;
          endif
       end if;
    end process;
         
                  
    process(SPI)
    begin
       if rising_edge(CLK_50) then   (this is the system clock)
          if SPI_ENA then                   (and this is the ENABLE for processing SPI signals)
             SCK =  <= NOT(SCK);
    
          ...here do the other SPI processes... (FSM to write MOSI, read MISO, count the bits, maybe control !CS...)
    
          end if;
       end if;
    end process;
    There may be other - better - solutions.
    AS already said: Iīm not familiar with writing HDL, there may be better experts


    Klaus
    Please donīt contact me via PM, because there is no time to respond to them. No friend requests. Thank you.


    1 members found this post helpful.

  12. #12
    Super Moderator
    Points: 249,725, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    43,472
    Helped
    13213 / 13213
    Points
    249,725
    Level
    100

    Re: Propper clock generation for SPI protocol

    Generation of clk_out in combinational logic involves the problem of possible glitches, thus it shouldn't be used as external signal, e.g. drive the SPI clock.

    A simple example how things can be done.
    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    PROCESS(clk,reset)
    BEGIN
      IF reset = '1' THEN
        bitcnt <= 0;
        nCS_DAC <= '1';
        DACCLK <= '0';
      ELSIF rising_edge(clk) THEN
        IF clkcnt > 0 THEN
          clkcnt <= clkcnt - 1;
        END IF;   
        CASE bitcnt IS
          WHEN 0 =>
            DACCLK <= '0';        
            IF start = '1' AND clkcnt = 0 THEN
              sr <= data;
              nCS_DAC <= '0';
              bitcnt <= 8;
              clkcnt <= 15;
            END IF;
          WHEN OTHERS =>
    -- SPI frequency = input frequency/16, 50% duty cycle                
            IF clkcnt = 8 THEN
              DACCLK <= '1';
            ELSIF clkcnt = 0 THEN    
              clkcnt <= 15;
              sr <= sr(6 downto 0) & "0";
              DACCLK <= '0';
              bitcnt <= bitcnt - 1;
              IF bitcnt = 1 THEN
                nCS_DAC <= '1';
              END IF;
            END IF;
          END CASE;      
      END IF;
    END PROCESS;
    MOSI <= sr(7);



  13. #13
    Junior Member level 3
    Points: 150, Level: 1

    Join Date
    Oct 2018
    Posts
    29
    Helped
    0 / 0
    Points
    150
    Level
    1

    Re: Propper clock generation for SPI protocol

    Ok, now I got the idea clearer.
    So Klaus, what you were telling to me on the I2C thread is what we are discussing on this one, isn't it?

    If that's the point I was missing, then I probably rewrite the code o fix it up.

    About the clocks on SPI, I just need one clock at a time. The idea of multiple clock speeds is just to make a generic module compatible with multiple devices, from temperature sensors to small screens.



    •   AltAdvertisment

        
       

  14. #14
    Super Moderator
    Points: 249,725, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    43,472
    Helped
    13213 / 13213
    Points
    249,725
    Level
    100

    Re: Propper clock generation for SPI protocol

    It's quite easy to switch a clock enable divider between different rates, the decision between SCK edges would be made a bit different than in my above example.

    Please review my comment about variable SPI speed in post #2, you should check if it's useable with your devices.



  15. #15
    Super Moderator
    Points: 67,586, Level: 63
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    13,823
    Helped
    3153 / 3153
    Points
    67,586
    Level
    63

    Re: Propper clock generation for SPI protocol

    Hi,

    So Klaus, what you were telling to me on the I2C thread is what we are discussing on this one, isn't it?
    Itīs a problem on how to treat clocks in a CPLD or FPGA, thus itīs a general problem writing correct HDL .... itīs no problem of generating I2C or SPI signals.

    Although possible I donīt recommend to generate different SCK (frequencies) at the same time. But you are free to generate several SCK_ENA at the same time .. and just select the one ENA signal you like.


    Klaus
    Please donīt contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



--[[ ]]--