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

minimum system clock required

Altera_Forum
Honored Contributor II
3,155 Views

Dears, I'm making a SPI interface in FPGA to interface with the SPI interface of a processor. The details as below: 

• SPI of processor will always act as master. Slave for FPGA. 

• SPI Clk: 25mhz 

• SPI working mode: SCK polarity=0; Phase=1; 

• SS Polarity: low effective 

• Data format: 16bit addr + 16bit data; MSB of addr indicates read(1)/write(0) operation 

 

 

I have finished VHDL code and test bench. (see attachment for source code, test bench and DO file for Modelsim ) 

RTL simulation has been done in Modelsim.  

In the simulation,system clock in FPGA was set to 100mhz. After simulation, no error found. 

Can I anounce that: this design can accept 25mhz SPI data if system clock is 100mhz? 

 

 

Or i ask this question in another way. If SPI clock remainis 25mhz, whaht is the minimum system clock required? What is the criteria?
0 Kudos
6 Replies
Altera_Forum
Honored Contributor II
1,195 Views

If you allow for SPI signal skew, asymmetrical SPI clock and arbitrary clock phase, the system clock frequency probably can't be much lower. You'll find out by adding these real world effects to your testbench. 

 

Alternatively you can run the SPI interface from SCK and perform domain crossing data transfer, e.g. using registers with handshake or DCFIFO. That's my usual choice for SPI clock frequencies in the multi 10 MHz range.
0 Kudos
Altera_Forum
Honored Contributor II
1,195 Views

Dear FvM, Thanks for your reply.  

I'm very interested on domain crossing data transfer. Could you show me more details?
0 Kudos
Altera_Forum
Honored Contributor II
1,195 Views

One more question, is there any metastability problem in my design?

0 Kudos
Altera_Forum
Honored Contributor II
1,195 Views

 

--- Quote Start ---  

One more question, is there any metastability problem in my design? 

--- Quote End ---  

 

Should be O.K. by double registering of SCK and SS. 

 

 

--- Quote Start ---  

Could you show me more details? 

--- Quote End ---  

 

Domain crossing data transfer is easy for write data, register the data in the SCK domain, transfer the update event to the sysclock domain, e.g. by a toggle synchronizer. The data can be expected to be stable and consistent when the update event arrives. 

 

Read data transfer is more difficult. A suitable method depends on the amount of data (number of different read addresses). A straightforward way is to have registers permanently updated by the sysclock, update is paused while synchronized SS is active. If you have too many data, it can be fetched after the address is decoded, possibly needing a few empty SPI clock cycles between address and data phase.
0 Kudos
Altera_Forum
Honored Contributor II
1,195 Views

Dear FvM, Based on your comments, I have made some code and simulated. See the code below. 

The working condition is completely the same as before except that the 7 bits after MSB of address word is used instead of the lower 8 bits. 

 

library work ; use work.package_group.all ; -------------------------------------------------------------------------------------------- -- ENTITY -------------------------------------------------------------------------------------------- entity spi is port ( clk : in std_logic ; ce : in std_logic ; rst : in std_logic ; -- spi port SS : in std_logic ; SCK : in std_logic ; MOSI : in std_logic ; MISO : inout std_logic ; -- Data registers rstack : in t_RegArray ; wstack : out t_RegArray ) ; end entity spi ; -------------------------------------------------------------------------------------------- -- ARCHITECTURE -------------------------------------------------------------------------------------------- architecture tran of spi is signal rst_spi : std_logic; signal cnt1 : std_logic_vector(4 downto 0); signal data_shift : std_logic_vector(31 downto 0); signal addr : std_logic_vector(6 downto 0); signal w_r : std_logic;--write: 0; read: 1 signal data_out : std_logic_vector(15 downto 0); --signal data_in : std_logic_vector(15 downto 0); begin rst_spi <= rst or SS; -- SS is low effective -- bit counter process(SCK,rst_spi) begin if rst_spi = '1' then cnt1 <= "11111"; elsif rising_edge(SCK) then cnt1 <= cnt1 + 1; end if; end process; --shift in data on MOSI process(SCK,rst_spi) begin if rst_spi = '1' then data_shift <= (others=>'0'); elsif falling_edge(SCK) then data_shift(31 - conv_integer(cnt1)) <= MOSI; end if; end process; --identify it's write or read process(SCK,rst_spi) begin if rst_spi = '1' then w_r <= '0'; elsif rising_edge(SCK) then if cnt1 = "00001" then w_r <= data_shift(31); end if; end if; end process; --get address process(SCK,rst_spi) begin if rst_spi = '1' then addr <= (others=>'0'); elsif rising_edge(SCK) then if cnt1 = "00111" then addr <= data_shift(30 downto 24); end if; end if; end process; --write data into write-only register array process(SCK,rst_spi) begin if rst = '1' then wstack (85) <= X"8888" ; wstack (90) <= X"9999" ; elsif falling_edge(SCK) then if cnt1 = "11111" and w_r = '0' then wstack(conv_integer(addr)) <= data_shift(15 downto 1) & MOSI; end if; end if; end process; --load data from read-only register array process(SCK,rst_spi) begin if rising_edge(SCK) then if cnt1 = "01000" and w_r = '1' then data_out <= rstack(conv_integer(addr)); end if; end if; end process; process(cnt1,data_out) begin case cnt1 is when "10000" => MISO <= data_out(15); when "10001" => MISO <= data_out(14); when "10010" => MISO <= data_out(13); when "10011" => MISO <= data_out(12); when "10100" => MISO <= data_out(11); when "10101" => MISO <= data_out(10); when "10110" => MISO <= data_out(9); when "10111" => MISO <= data_out(8); when "11000" => MISO <= data_out(7); when "11001" => MISO <= data_out(6); when "11010" => MISO <= data_out(5); when "11011" => MISO <= data_out(4); when "11100" => MISO <= data_out(3); when "11101" => MISO <= data_out(2); when "11110" => MISO <= data_out(1); when "11111" => MISO <= data_out(0); when others => MISO <= '0'; end case; end process; end architecture tran ; 

 

Can you give me some comments? Is there anything not good and can be improved?  

 

Compare to the previous solution i made, i feel this new solution you suggested is much better. The 2 advantages are: 

1. The spi clock is completely independent of system clock. That means SPI clock can go very high. Maybe the limit for the speed is from the FPGA device itself.  

2. Chance to have metastability problem is zero because data is synchronized with SPI clock.  

 

Are the statements above correct?
0 Kudos
Altera_Forum
Honored Contributor II
1,195 Views

can anybody help?

0 Kudos
Reply