I am trying to interface a Virtex 4 (ML401) FPGA and a TIVA C series board using 4 wire SPI (cs, sclk, miso, mosi). The tiva acts as a master and the FPGA as a slave. I am able to receive the SPI data from the master and display the data on the LEDS present on the FPGA (Method 2). However, I need to find the rising and falling transitions of the chip select signal (required for my application for synchronization purposes). I have tried many methods with FIFO's (that work well in simulation) but just don't work on the FPGA, as shown:
NOTE: spi_cs is the asynchronous SPI chip select signal input to the FPGA from the TIVA board, while other signals (spi_cs_s, spi_cs_ss, spi_cs_h2l, spi_cs_l2h, etc) are created internally on the FPGA.
Method 1)
prc_sync_cs: process(clk)
begin
if (clk'event and clk = '1') then
spi_cs_s <= spi_cs;
end if;
end process prc_sync_cs;
spi_cs_l2h <= not (spi_cs_s) and spi_cs;
spi_cs_h2l <= not (spi_cs) and spi_cs_s;
Method 2)
process (spi_cs)
begin
if (spi_cs = '0' or spi_cs = '1') then
-- update ledss with new MOSI on rising edge of CS
spi_cs_ss <= spi_cs_s;
spi_cs_s <= spi_cs;
--leds <= spi_wdata; --leds display the received data on the FPGA (saved into spi_wdata in another process)
-- THIS WORKS ON THE FGPA BUT the edge detection doesn't. Why?
end if;
end process;
spi_cs_h2l <= '1' when (spi_cs_s = '0' and spi_cs_ss = '1') else '0';
spi_cs_l2h <= '1' when (spi_cs_s = '1' and spi_cs_ss = '0') else '0';
leds <= "000000" & spi_cs_h2l & spi_cs_l2h; -- ALL leds are off always (i,e both transitions are '0' always).
Method 3)
prc_sync_cs: process(clk)
begin
if (clk'event and clk = '1') then
spi_cs_ss <= spi_cs_s;
spi_cs_s <= spi_cs;
end if;
end process prc_sync_cs;
prc_edge_cs: process(clk)
begin
if (clk'event and clk = '1') then
spi_cs_ss_del <= spi_cs_ss;
end if;
end process prc_edge_cs;
spi_cs_h2l <= '1' when (spi_cs_ss_del = '1' and spi_cs_ss = '0') else '0';
spi_cs_l2h <= '1' when (spi_cs_ss_del = '0' and spi_cs_ss = '1') else '0';
ALL the methods work perfectly in simulation but not when downloaded on the FPGA. I wrote a process to monitor the transitions more closely (to monitor metastable values, if any):
led_test: process(spi_cs_h2l, spi_cs_l2h)
begin
if spi_cs_h2l = '1' or spi_cs_l2h = '1' then
leds <= "111100" & spi_cs_h2l & spi_cs_l2h;
elsif spi_cs_h2l = 'X' or spi_cs_h2l = 'U' or spi_cs_h2l = 'Z' or
spi_cs_l2h = 'X' or spi_cs_l2h = 'U' or spi_cs_l2h = 'Z' then
leds <= "00001111";
else
leds <= "10101010";
end if;
end process led_test;
The leds are always "10101010" i.e is the else case where both spi_cs_h2l and spi_cs_l2h are = '0'. What am I missing ?? Any pointers would be very helpful as I am stuck with this issue since many days.
UPDATE
Using method 3 of clock domain crossing (as suggested by Jeff), and by initializing all the leds and signals to zero, the process to light up the leds is changed as follows:
led_test: process(spi_cs_h2l)
begin
if rising_edge(clk) then
if spi_cs_h2l = '1' then
leds <= "11110011";
end if;
end if;
end process led_test;
At least one high to low transition of the chip select pin is expected to light up the leds. The SPI chip select pin is receiving a '1' always and when FPGA is started/reset, the leds light up. How is this possible? How can this false high to low transition occur ?
clk
in your code synchronous tospi_cs
, or is it just other clock in the FPGA? – scary_jeff