Guest
Hello everyone!
I'm trying to design an SPI slave component in VHDL for Spartan-6.
I don't have problems with receiving a byte, but some strange things happen when I try to send a byte to a master device.
Since I don't have too much experience with VHDL, can someone please take a look at this simple program and tell me what did I do wrong.
I'm trying to send a byte 0xA6 from the slave to the master. However, for some reason, my SPI slave sends 0xA6, but also 0xB4 and 0xD3 occasionally.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
entity spi_slave is
port(
clk : in std_logic; -- 50 MHz clock
rst_n : in std_logic; -- asynchronous reset (active low)
ss_n : in std_logic; -- SPI slave select (active low)
sck : in std_logic; -- SPI clock
--mosi : in std_logic; -- master out, slave in (not in use)
miso : out std_logic -- master in, slave out
);
end entity spi_slave;
architecture RTL of spi_slave is
-- registers
signal ss_n_q : std_logic;
signal sck_q, sck0_q : std_logic;
--signal mosi_q : std_logic;
signal miso_q : std_logic;
signal cnt_q : natural range 0 to 7; -- counter that counts how many bits have been received
constant din : std_logic_vector(7 downto 0) := "10100110"; -- 0xA6
begin
miso <= miso_q;
spi_slave_logic : process(clk, rst_n, ss_n_q, sck_q, sck0_q, cnt_q, miso_q) is
-- wires
variable miso_d : std_logic;
variable cnt_d : natural range 0 to 7;
begin
miso_d := miso_q;
cnt_d := cnt_q;
if ss_n_q='1' then -- slave is not selected
cnt_d := 0; -- reset counter
miso_d := din(7); -- set the MSB at the output
else
if (sck0_q='0' and sck_q='1') then -- SPI clock rising edge
cnt_d := (cnt_q+1) rem 8;
elsif (sck0_q='1' and sck_q='0') then -- SPI clock falling edge
miso_d := din(7-cnt_q);
end if;
end if;
-- latch wires to registers
if rst_n='0' then
null; -- to be implemented
elsif rising_edge(clk) then
ss_n_q <= ss_n;
sck_q <= sck; -- present clock
sck0_q <= sck_q; -- past clock
--mosi_q <= mosi;
miso_q <= miso_d;
cnt_q <= cnt_d;
end if;
end process spi_slave_logic;
end architecture RTL;
I'm trying to design an SPI slave component in VHDL for Spartan-6.
I don't have problems with receiving a byte, but some strange things happen when I try to send a byte to a master device.
Since I don't have too much experience with VHDL, can someone please take a look at this simple program and tell me what did I do wrong.
I'm trying to send a byte 0xA6 from the slave to the master. However, for some reason, my SPI slave sends 0xA6, but also 0xB4 and 0xD3 occasionally.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
entity spi_slave is
port(
clk : in std_logic; -- 50 MHz clock
rst_n : in std_logic; -- asynchronous reset (active low)
ss_n : in std_logic; -- SPI slave select (active low)
sck : in std_logic; -- SPI clock
--mosi : in std_logic; -- master out, slave in (not in use)
miso : out std_logic -- master in, slave out
);
end entity spi_slave;
architecture RTL of spi_slave is
-- registers
signal ss_n_q : std_logic;
signal sck_q, sck0_q : std_logic;
--signal mosi_q : std_logic;
signal miso_q : std_logic;
signal cnt_q : natural range 0 to 7; -- counter that counts how many bits have been received
constant din : std_logic_vector(7 downto 0) := "10100110"; -- 0xA6
begin
miso <= miso_q;
spi_slave_logic : process(clk, rst_n, ss_n_q, sck_q, sck0_q, cnt_q, miso_q) is
-- wires
variable miso_d : std_logic;
variable cnt_d : natural range 0 to 7;
begin
miso_d := miso_q;
cnt_d := cnt_q;
if ss_n_q='1' then -- slave is not selected
cnt_d := 0; -- reset counter
miso_d := din(7); -- set the MSB at the output
else
if (sck0_q='0' and sck_q='1') then -- SPI clock rising edge
cnt_d := (cnt_q+1) rem 8;
elsif (sck0_q='1' and sck_q='0') then -- SPI clock falling edge
miso_d := din(7-cnt_q);
end if;
end if;
-- latch wires to registers
if rst_n='0' then
null; -- to be implemented
elsif rising_edge(clk) then
ss_n_q <= ss_n;
sck_q <= sck; -- present clock
sck0_q <= sck_q; -- past clock
--mosi_q <= mosi;
miso_q <= miso_d;
cnt_q <= cnt_d;
end if;
end process spi_slave_logic;
end architecture RTL;