Nios® II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
Intel Support hours are Monday-Fridays, 8am-5pm PST, except Holidays. Thanks to our community members who provide support during our down time or before we get to your questions. We appreciate you!

Need Forum Guidance? Click here
Search our FPGA Knowledge Articles here.

Nios as slave with spi

Honored Contributor I

Hello guys, I'm writing beacause I need some suggestions.. 


I have an FPGA running a NIOS2 processor. This processor will be interrogated by a master peripheral with the SPI protocol. I know that it's possible to configure the SPI with a software interrupt. 


By the way I'm not sure about how configuring the SPI peripheral as slave. Actually I receive some strings with different lengths from the master system, than I have to extrapolate the informations contained in these strings, do some elaboration and finally send the answer message if needed (that are other strings with different lenghts). 


Sumnmarizing I need to read the string sent by the host then have enaugh time to elaborate the information and finally send the answer message.  


So I thought to enable the interrupt on the SPI and get the string from the master, when the string is received set a register to 0. Now the master must poll the register until goes to 1 before give me the clock necessary to have the answer message transmitted. 


How can I do the "register thing" ? There are better options ? 





One more thing.. I saw that the SPI has a fixed bitsize, so if I have to receive a string with a non fixed length how can I manage the SPI configuration ? 

I want to accomplish something like this  

in which the length of the bitstream is only defined by the edge of the SSN.
0 Kudos
5 Replies
Honored Contributor I

To get rid of the fixed-size problems, I can recommend you to build your own SPI interface. You can add PIO's to your system design and modify your top-level entity file and change their Inputs and outputs as signals. For example I have used a slave device (wiz550io) which waits for 32-bits SPI signal for writing to a register and for reading you first write 24-bits and receive the 8-bits in the same frame. For this reason I prepared a 32-bits PIO for writing, a 8-bits PIO for reading and another PIO to control, I added an extra process into my top-level entity and also added MISO, MOSI, CLK, CS as new ports and I am dividing clock to create the clock for SPI. 


For your situation, you can use the incoming spi clock to trigger your process and write the incoming data to a reading PIO register. To receive an interrupt you can assign another PIO block with IRQ.
Honored Contributor I

Thank you oakbati. Please could you be more detailed ? I have not understood your point very well.. 


Have a nice day !!
Honored Contributor I

By the spi core docs (june 2011): 


"..After a word is received by the slave, the master must de-asser the ss_n signal and reasserts the signal again when the next word is ready to be sent.." 


So it seems that if you want to use the Altera's SPI interface you cannot transfer strings with variable byte length with the ssn low for all the time necessary to the transmission.
Honored Contributor I

For example port defs in your vhdl (I use vhdl) should be modified as (disable pio's that become input or outputs and add miso mosi sclk scs, following example is for master spi) 


entity yourprog is 

port ( 

clk_clk : in std_logic := '0'; -- clk.clk 

leds_export : out std_logic_vector(7 downto 0); -- leds.export 

--input1_export : in std_logic_vector(7 downto 0) := (others => '0'); -- input1.export 

--output1_export : out std_logic_vector(7 downto 0); -- output1.export 

--spi_wr_export : out std_logic_vector(31 downto 0); -- spi_wr.export 

--spi_rd_export : in std_logic_vector(7 downto 0) := (others => '0') -- spi_rd.export 

MOSI : out std_logic:='0'; 

MISO : in std_logic; 

SCLK : out std_logic:='0'; 

SCS : out std_logic:='1' 


end entity yourprog; 


Then you should define those disabled variables as signals to be used in your process... 


signal input1_export : std_logic_vector(7 downto 0) := (others => '0'); -- input1.export 

signal output1_export : std_logic_vector(7 downto 0); -- output1.export 

signal spi_wr_export : std_logic_vector(31 downto 0); -- spi_wr.export 

signal spi_rd_export : std_logic_vector(7 downto 0) := (others => '0'); -- spi_rd.export 


Then you can add a process depending on your status... (following code is my master spi code, it uses a counter named counter_spi and increased by clk) 


process (clk_clk) 


if(output1_export(0) = '1' and output1_export(0)'event) then 

input1_export(0) <= '1'; 

end if; 

if (clk_clk = '1' and clk_clk'event and input1_export(0) = '1') then 

counter_spi <= counter_spi + '1'; 

end if; 

if (counter_spi = "1111111111") then 

input1_export(0) <= '0'; 

counter_spi <= "0000000000"; 

end if; 

end process; 


process (counter_spi) 


if (counter_spi(1) = '1' and counter_spi(1)'event) then 


if(counter_spi(9)='0' and spi_wr_export(10) = '1' and counter_spi(3)='0') then 

MOSI <= spi_wr_export(31-conv_integer(counter_spi(8 downto 4))); 

spi_rd_export <= X"55"; 

end if; 


if(counter_spi(9)='0' and spi_wr_export(10) = '0') then 

if(counter_spi(8 downto 4)<"11000" and counter_spi(3)='0') then 

MOSI <= spi_wr_export(31-conv_integer(counter_spi(8 downto 4))); 

end if; 

if(counter_spi(8 downto 4)>="11000" and counter_spi(3)='1') then 

spi_rd_export(7-conv_integer(counter_spi(6 downto 4))) <= MISO; 

--spi_rd_export(7-conv_integer(counter_spi(6 downto 4))) <= spi_wr_export(31-conv_integer(counter_spi(6 downto 4))); 

end if; 

end if; 


SCLK <= counter_spi(3) and (not counter_spi(9)); 

if (counter_spi(9) = '1' and counter_spi(5) = '1') then 

SCSn <= '1'; 

end if; 

if (counter_spi(9) = '0' and input1_export(0) = '1') then 

SCSn <= '0'; 

end if; 


input1_export(1) <= RDY; 

input1_export(2) <= Intn; 

input1_export(3) <= counter_spi(3) and (not counter_spi(9)); 

RSTn <= output1_export(2); 

end if;  

end process; 


You should create your own spi process to act as a slave, instead of using a counter depending on internal clock, you should use the external clock supplied by your external spi master.
Honored Contributor I

Ty oakbati. I'm working on it !! 


Have anice day !