Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
17268 Discussions

Altera DE0-nano. Struggling to make a SPI slave device

Altera_Forum
Honored Contributor II
1,193 Views

Hi. I'm new to VHDL and I thought I could try to make a slave SPI device as training, but it's not working quite as expected. Below my current code. It's compiles and upload just fine, but it's not working as intended. Right now I have the leds connected to the signal "bitnumber", bitnumber is supposed to increment on each rising edge of CLK and then reset to zero when the SS pin is pulled LOW (indicating that the transfer is complete), but it doesn't do that. I've connected my Altera DE0-nano to my arduino which is simply pulling the SS LOW, sends four clock pulses and then pulls the SS back high, I've put a 1s delay between each transition. The leds on my altera board does change it's pattern every second, but it does so on both rising and falling edge of the clock, also the led pattern seems completely random, even showing some leds in a dimmed state. The leds become black when the SS pin goes back HIGH though, that's good. 

 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity SPI2 is PORT (LED : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); GPIO_0 : IN STD_LOGIC_VECTOR(7 DOWNTO 0)); end SPI2; architecture SPI2_beh of SPI2 is signal SPIdataregister : STD_LOGIC_VECTOR(7 DOWNTO 0); signal bitnumber : STD_LOGIC_VECTOR(7 DOWNTO 0); begin LED <= bitnumber; process(GPIO_0(5), GPIO_0(3)) begin if ((GPIO_0(5)) = '1') then bitnumber <= (bitnumber + '1'); end if; if ((GPIO_0(3)) = '1') then bitnumber <= "00000000"; end if; end process; process(bitnumber) begin case bitnumber is when "00000001" => SPIdataregister(0) <= GPIO_0(7); when "00000010" => SPIdataregister(1) <= GPIO_0(7); when "00000011" => SPIdataregister(2) <= GPIO_0(7); when "00000100" => SPIdataregister(3) <= GPIO_0(7); when "00000101" => SPIdataregister(4) <= GPIO_0(7); when "00000110" => SPIdataregister(5) <= GPIO_0(7); when "00000111" => SPIdataregister(6) <= GPIO_0(7); when "00001000" => SPIdataregister(7) <= GPIO_0(7); when others => SPIdataregister <= SPIdataregister; end case; end process; end SPI2_beh;
0 Kudos
1 Reply
Altera_Forum
Honored Contributor II
512 Views

The main problem with your code is that it isn't synchronous. A VHDL simulator may simulate your code correctly because it will only execute the first process when one of your GPIO signals will change, but a VHDL synthesizer will not know what to do with your code. 

I suggest to use a clock and make the first process a regular clocked process. The DE0 kit should have an on-board oscillator that you can use. Then you will need to change your process a bit. The part with the reset pin can be used as is, but for the clock signal you will need to detect a rising edge. The recommended way of doing that is to create an extra signal that will hold the previous value of GPIO_0(5). Then if that signal is '0' and GPIO_0(5) is '1', it means you have a rising edge and you can increase bitnumber. 

 

Also it isn't recommended to use IEEE.STD_LOGIC_UNSIGNED.ALL because it isn't a standard library, and it will cause problems if you try to mix unsigned and signed values, or try to use other libraries. The recommended way is to use IEEE.NUMERIC_STD.ALL instead, and make your bitnumber an "unsigned" type instead of "std_logic_vector". You can use the rest of the code as is, except for LED, as you will need to cast bitnumber back to the vector type:LED <= std_logic_vector(bitnumber);
0 Kudos
Reply