A question about sclk edge
Seven-Zeng opened this issue · comments
Hi man,
I have to say that your code looks so comfortable.
I'm a rookie of FPGA designing and have some questions hope that you can help:
- would that be a problem to shift data on rising edge of CLK together with checking spi_clk_redge_en level? As the spi_clk_redge_en is derived from spi_clk_reg, which is latch on rising edge of CLK as well, which means the spi_clk_redge_en might alter on rising edge of CLK.
- I have viewed many implementations of SPI slave, some of them use synchronized clock to latch or shift data in/out just like yours, while others use the sclk directly, which one would be better? and why?
- CAN CS_n be used as RST directly?
Hi,
- The shift register (data_shreg) capture incoming data from master in CLK cycle, when a rising edge was detected (spi_clk_redge_en) on the SCLK signal. But I have a bug #5, SCLK should be synchronized (two FFs) to the CKL clock domain. Timing diagram of current implementation:
CLK _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_
SCLK (async) ___________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾|______________
spi_clk_reg _____________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|___________
spi_clk_redge_en ___________|‾|___________________________
data_shreg D0...........|D1.........................
-
Both implementations have advantages and disadvantages. For example my solution does not require a more complex cross domain crossing from SCLK to CLK (asynchronous FIFO) and all FFs are active on the rising edge of the same clock
-
No, RST is typically a global FPGA reset. CS_N is used to select the SPI slave module. My SPI slave module allows to accept user data to be transmitted even when not active CS_N.
Hi,
The diagram illustrated you intention so clearly, while, forgive my silly, there still one point I haven't gotten:
the code is like:
data_shreg_p : process (CLK)
begin
if (rising_edge(CLK)) then
if (load_data_en = '1') then
data_shreg <= DIN;
elsif (spi_clk_redge_en = '1' and CS_N = '0') then
data_shreg <= data_shreg(6 downto 0) & MOSI;
CLK _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_
SCLK (async) ___________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾|______________
spi_clk_reg _____________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|___________
spi_clk_redge_en ___________|‾|___________________________
data_shreg D0..............|D1.........................
------------------------------^---------------------------
the bit is latched on the rising edge AND spi_clk_redge_en == '1', but spi_clk_redge_en is reset to '0' at exactly the same rising edge of the CLK, what if spi_clk_redge_en falls to zero before the bit shift condition is checked? Is that gonna be a risk?
Besides, when you say add another FF do you mean implementing it like this:
CLK _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_
SCLK (async) ___________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾|______________
spi_clk_reg1 _____________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|___________
spi_clk_reg2 _________________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|___________
spi_clk_redge_en _____________|‾‾‾|___________________________
data_shreg D0...............|D1.........................
The described situation cannot occur. From sampling theorem: CLK clock must be more than twice as fast as SCLK. For reliable data transmission, I have a much stricter condition on my SPI master (SCLK_FREQ <= CLK_FREQ/10).
The problem may be when spi_clk_redge_en is set at the same time as rising edge of the CLK. This problem can cause metastability (bug #5) and can be solved by adding at least two FFs. Yes your diagram corresponds to an implementation with one FF added.
Got you!
Many thanks !