----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 14:08:05 04/09/2015
-- Design Name:
-- Module Name: spi_master - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity spi_master is
generic (
CLK_DIV : std_logic_vector(7 downto 0) := x"05"
);
Port ( rst : in STD_LOGIC; -- reset signal, active '1'
clk : in STD_LOGIC; -- 40MHz
cs_ctrl : in STD_LOGIC; -- CS control
data_in : in STD_LOGIC_VECTOR (7 downto 0);
data_out : out STD_LOGIC_VECTOR (7 downto 0);
data_valid : out STD_LOGIC;
spi_send : in STD_LOGIC;
spi_busy : out STD_LOGIC;
cs : out STD_LOGIC; -- same as CS_CTRL
sclk : out STD_LOGIC;
mosi : out STD_LOGIC;
miso : in STD_LOGIC);
end spi_master;
architecture Behavioral of spi_master is
constant RESET_ACTIVE : std_logic := '1';
-- constant CLK_DIV : std_logic_vector(7 downto 0) := x"01";
signal reg_tx : std_logic_vector(7 downto 0);
signal reg_rx : std_logic_vector(7 downto 0);
signal send : std_logic_vector(1 downto 0);
signal sck : std_logic;
signal clk_en : std_logic;
signal t_clk : std_logic_vector(7 downto 0); --1/2CLK counter
signal ct_bit : std_logic_vector(7 downto 0);--send bits counter
type state_type is (idle,tx_prep,tx_state,tx_end);
signal currt_state, next_state : state_type;
begin
process(clk,rst) -- SPI send active
begin
if rst = RESET_ACTIVE then
send <= "00";
elsif rising_edge(clk) then
send(0) <= spi_send;
send(1) <= send(0);
end if;
end process;
process(rst,clk) --generate SPI SCLK
begin
if rst = RESET_ACTIVE then
t_clk <= x"00";
ct_bit <= x"00";
sck <= '0';
elsif rising_edge(clk) then
if clk_en = '1' then
if t_clk = CLK_DIV then
t_clk <= x"00";
ct_bit <= ct_bit + '1';
sck <= not(sck);
else
t_clk <= t_clk + '1';
end if;
else
t_clk <= x"00";
ct_bit <= x"00";
sck <= '0';
end if;
end if;
end process;
sclk <= sck; --64 divider
process(next_state,rst) --SPI state meachine
begin
if rst = RESET_ACTIVE then
currt_state <= idle;
else
currt_state <= next_state;
end if;
end process;
cs <= cs_ctrl;
process(clk,rst)
begin
if rst = RESET_ACTIVE then
-- cs <= '1';
mosi <= '0';
clk_en <= '0';
reg_tx <= (others => '0');
reg_rx <= (others => '0');
data_out <= (others => '0');
next_state <= idle;
data_valid <= '0';
spi_busy <= '0';
elsif rising_edge(clk) then
case currt_state is
when idle =>
-- cs <= '1';
mosi <= '0';
clk_en <= '0';
reg_tx <= (others => '0');
next_state <= idle;
if send = "01" then -- posedge send
reg_tx <= data_in;
clk_en <= '0';
next_state <= tx_prep;
end if;
spi_busy <= '0';
when tx_prep =>
-- cs <= '0';
mosi <= reg_tx(7);
clk_en <= '1';
next_state <= tx_state;
spi_busy <= '1';
when tx_state =>
if ct_bit(0) = '0' and t_clk = CLK_DIV then --SCLK posedge
reg_rx <= reg_rx(6 downto 0) & miso;
next_state <= tx_state;
clk_en <= '1';
reg_tx <= reg_tx(6 downto 0) & '0';
elsif ct_bit(0) = '1' and t_clk = CLK_DIV then --SCLK negedge
mosi <= reg_tx(7);
next_state <= tx_state;
clk_en <= '1';
elsif ct_bit = x"10" and t_clk = (CLK_DIV-'1') then --the last data
-- cs <= '0';
clk_en <= '0';
--mosi <= '0';
next_state <= tx_end;
-- if CLK_DIV = x"01" then
-- data_out <= reg_rx;
-- end if;
elsif ct_bit = x"10" then
data_valid <= '1';
data_out <= reg_rx;
else
-- cs <= '0';
clk_en <= '1';
next_state <= tx_state;
end if;
when tx_end =>
-- cs <= '1';
clk_en <= '0';
mosi <= '0';
next_state <= idle;
spi_busy <= '0';
data_valid <= '0';
end case;
end if;
end process;
end Behavioral;
spi--master
最新推荐文章于 2023-05-25 13:46:51 发布