Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

Building an SPI Decoder into Altera

Hello,

I am working on a project which requires interfacing between a Microcontroller and an Altera FPGA. I'm using an Arduino UNO and DE0Nano Cyclone IV. The Arduino sends a 64bit word via SPI into the Altera. This word has been verified using a Logic Analyzer, and it seems to be stable and correct. In order to read the 64 bits, I am loading everything into a shift register. This procedure works as well since my outputs are correct. The first process in the code snippet below reads the data through SPI, making sure the Selector is active low and reading on the RE of the clock. The second process decodes the 64 bit word into the specific outputs I need. It does this at the end of a data transmission, when the Selector is going back to the idle state High.

The issue I'm running into is when the circuit is idle, when SPI is not running in the Microcontroller. From the code, since SPI_Sel is High and SPI_Clk is not operating, I expect the shift register to be set to 0 and no value should change. However, this is not the case and I get a flickering in my values. If I remove the line where I load into the shift_reg64(63 downto 0), this flickering stops and obviously nothing happens. Since, the flickering stops, I believe that data is being loaded and read from the shift register without it being ready. Does anyone have any idea of what may be causing this?

Thank you very much! Below is the code I'm referencing.


process (SPI_Clk, SPI_Data, SPI_Sel, shift_reg64) begin
		if rising_edge (SPI_Clk) then
			if (SPI_Sel = '0') then
				--shift data in and load new
				shift_reg64(63 downto 0) <= shift_reg64(62 downto 0) & SPI_Data;
			end if;
		end if;
	
end process;
process (SPI_Sel, shift_reg64) begin
	if rising_edge(SPI_Sel) then
		outA <= "000" & shift_reg64(60 downto 32);
		outB <= "000" & shift_reg64(28 downto 0);
		SEL_h <= shift_reg64(63 downto 61);
		SEL_l <= shift_reg64(31 downto 29);-
	end if;
end process;

13 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You're using an asynchronous signal as a clock, bad idea.

    If you want to use SPI select deasserting to indicate when to load a parallel output register, then you can use exactly the same edge-detection technique to generate a pulse when SPI_sel deasserts. You need to have a dual-DFF synchronizer, followed by your edge-detect logic.

    Change the process to use your FPGA clock, and use the spi_sel_rising_edge pulse to enable your parallel output registers at the end of each SPI transaction.

    Cheers,

    Dave
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Great! I believe this worked! Just to make sure though, I still have a doubt on using the dual DFF synchronizer and the edge-detection logic.

    Take I have my input SPI_Clk going into DFF1 and Q1 going into DFF2. Q2' is NOTed and ANDed with Q1. This give the SPI_rising_edge.

    I really appreciate your help!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Just to make sure though, I still have a doubt on using the dual DFF synchronizer and the edge-detection logic.

    Take I have my input SPI_Clk going into DFF1 and Q1 going into DFF2. Q2' is NOTed and ANDed with Q1. This give the SPI_rising_edge.

    --- Quote End ---

    Post your code (upload it as an attachment, don't post it inline). I'll take a look at it. Bonus points if you can create a Modelsim simulation :)

    Cheers,

    Dave