Цитата
В соотвествии с принципами SPI сигнал slave select следует использовать, как асинхронный сброс приёмника по пассивному уровню ss(то есть когда приёмник не должен работать).
SPI тут не классический, поэтому по-другому немного. Переписал код, вроде бы всё синхронно сделал, но теперь после синтеза при моделировании не появляется выходной сигнал (строб есть). Хотя до синтеза всё в порядке...
Код
LIBRARY ieee;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
ENTITY spi_slave IS
GENERIC(
d_width : INTEGER := 12); --data width in bits
PORT
(
Clk : IN STD_LOGIC;
Shift : IN STD_LOGIC;
Mosi : IN STD_LOGIC;
Data1 : out std_logic_vector(d_width-3 downto 0);
Data2 : out std_logic_vector(d_width-3 downto 0);
Strob : in std_logic
);
END spi_slave;
ARCHITECTURE logic OF spi_slave IS
signal buff : STD_LOGIC_vector(d_width-1 downto 0) := (others => '0');
signal mega_buff : STD_LOGIC_vector(d_width-1 downto 0);
signal reg1 : STD_LOGIC_vector(d_width-3 downto 0);-- := (others => '0');
signal reg2 : STD_LOGIC_vector(d_width-3 downto 0);-- := (others => '0');
signal bit_counter : std_logic_vector (d_width-1 downto 0) := (others => '0');
signal res : std_logic := '0';
BEGIN
process(Shift,Clk)
begin
if(falling_edge(Clk) and Shift = '1') then
if(bit_counter = d_width+1) then
bit_counter <= (others => '0');
else
buff <= Mosi & buff(d_width-1 downto 1);
bit_counter <= bit_counter + 1;
end if;
end if;
end process;
process(Strob, Clk)
begin
if(falling_edge(Clk) and Strob = '1') then
case(buff(1)) is
when '0' => Data1 <= buff(d_width-1 downto 2);
when '1' => Data2 <= buff(d_width-1 downto 2);
when others => null;
end case;
end if;
end process;
END logic;
TB:
Код
LIBRARY ieee;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity testbench is
GENERIC(
d_width : INTEGER := 12);
end testbench;
architecture SPI_test of testbench is
component spi_slave is
port
(
Clk : IN STD_LOGIC; --spi clk from master
Shift : IN STD_LOGIC; --active low slave select
Mosi : IN STD_LOGIC;
Strob : in STD_LOGIC;
Data1 : out std_logic_vector(d_width-3 downto 0);
Data2 : out std_logic_vector(d_width-3 downto 0)
);
end component;
signal kod : std_logic_vector( 11 DOWNTO 0 ) := "101100010110";
signal clock : std_logic := '0';
signal clk_in : std_logic;
signal data1_out : std_logic_vector( d_width-3 DOWNTO 0 );
signal data2_out : std_logic_vector( d_width-3 DOWNTO 0 );
signal start : std_logic := '0';
signal stop : std_logic := '0';
signal start_strob : std_logic := '0';
signal stop_strob : std_logic := '0';
signal mosi_tb : std_logic;
signal counter : std_logic_vector( d_width-1 DOWNTO 0 ) :=(others => '0');
signal strob_counter : std_logic_vector( d_width-1 DOWNTO 0 ) :=(others => '0');
signal ss : std_logic := '0';
signal stb : std_logic := '0';
begin
start <= '1' after 110 ns;
clk : PROCESS(clock)
BEGIN
IF clock = '1' THEN
clock <= '0' after 25 ns;
ELSIF true THEN
clock <= '1' after 25 ns;
END IF;
clk_in <= clock;
END PROCESS;
data : PROCESS(clk_in, start)
BEGIN
if(falling_edge(clk_in) and start = '1') then
if(falling_edge(clk_in) and counter = d_width) then
counter <= (others => '0');
stop <= '1';
start_strob <= '1';
else
mosi_tb <= kod(0);
counter <= counter + 1;
kod <= '0' & kod(d_width-1 downto 1);
end if;
end if;
END PROCESS;
ss <= start and (not stop);
stb <= start_strob and (not stop_strob);
sb : process(stb, clk_in)
begin
if(falling_edge(clk_in) and stb = '1')then
if(falling_edge(clk_in) and strob_counter = 2)then
strob_counter <= (others => '0');
stop_strob <= '1';
else
strob_counter <= strob_counter + 1;
end if;
end if;
end process;
spi_slave_0 : spi_slave
port map
(
Clk => clk_in,
Shift => ss,
Strob => stb,
Mosi => mosi_tb,
Data1 => data1_out,
Data2 => data2_out
);
end SPI_test;