?? spi_control_sm.vhd
字號:
-- File: spi_control_sm.vhd
--
-- Created: 8-23-00 ALS
-- This file contains the overall control of the SPI interface. It generates the slave
-- select signals and the masks so that the SCK signals output to the SPI bus align properly
-- with the data. It generates the control signals to the shift register and the receive
-- data register.
--
-- This SPI interface operates on bytes of data. When the START signal from the uC is
-- asserted the byte-wide data in the SPI transmit register is transmitted on the SPI bus.
-- When this transfer is complete, the BUSY signal is negated and the START signal is
-- sampled. If the START signal is still asserted indicating that the uC has put new
-- data in the SPI transmit register, the data in the transmit register will be transmitted.
-- Each byte of data received from the SPI bus is captured in the receive register.The uC can
-- read this data once the BUSY signal has negated.
--
-- Revised: 9-6-00 ALS
-- Revised: 9-12-00 ALS
-- Revised: 10-17-00 ALS
-- Revised: 10-19-00 ALS
-- Revised: 10-27-00 ALS
-- Revised: 12-12-02 JRH
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity spi_control_sm is
port(
-- internal uC interface signals
start : in std_logic; -- start transfer
done : out std_logic; -- byte transfer is complete
rcv_load : in std_logic; -- load control signal to spi receive register
ss_mask_reg : in std_logic_vector(7 downto 0); -- uc slave select register
ss_in_int : inout std_logic; -- internal sampled version of ss_in_n needed by
-- uc to generate an interrupt
xmit_empty : inout std_logic; -- flag indicating that spitr is empty
xmit_empty_reset : in std_logic; -- xmit empty flag reset when spitr is written
rcv_full : out std_logic; -- flag indicating that spirr has new data
rcv_full_reset : in std_logic; -- rcv full flag reset when spirr is read
cpha : in std_logic; -- clock phase from uc
cpol : in std_logic; -- clock polarity from uc
-- spi interface signals
ss_n : out std_logic_vector(7 downto 0); -- slave select signals
ss_in_n : in std_logic; -- input slave select indicating master bus contention
ss_n_int : inout std_logic; -- internal ss_n that is masked with
-- slave select register
-- internal interface signals
sck_int : in std_logic; -- internal version of sck with cpha=1
sck_int_re : in std_logic; -- indicates rising edge on internal sck
sck_int_fe : in std_logic; -- indicates falling edge on internal sck
sck_re : in std_logic; -- indicates rising edge on external sck
sck_fe : in std_logic; -- indicates falling edge on external sck
xmit_shift : out std_logic; -- shift control signal to spi xmit shift register
xmit_load : inout std_logic; -- load control signal to the spi xmit shift register
clk1_mask : out std_logic; -- masks cpha=1 version of sck
clk0_mask : out std_logic; -- masks cpha=0 version of sck
-- clock and reset
reset : in std_logic; -- active low reset
clk : in std_logic -- clock
);
end spi_control_sm;
architecture DEFINITION of spi_control_sm is
--**************************** Constants ***************************************
constant RESET_ACTIVE : std_logic := '0';
constant EIGHT : std_logic_vector(3 downto 0) := "1000";
--**************************** Signals ***************************************
type SPI_STATE_TYPE is (IDLE, ASSERT_SSN1, ASSERT_SSN2, UNMASK_SCK, XFER_BIT,
ASSERT_DONE, CHK_START, MASK_SCK, HOLD_SSN1, HOLD_SSN2,
NEGATE_SSN);
signal spi_state, next_spi_state : SPI_STATE_TYPE;
signal bit_cnt : STD_LOGIC_VECTOR(3 downto 0); -- bit counter output
signal bit_cnt_en : STD_LOGIC; -- count enable for bit counter
signal bit_cnt_rst : STD_LOGIC; -- reset for bit counter from SPI
-- control state machine
signal bit_cnt_reset : STD_LOGIC; -- reset to bit counter that includes
-- SS_IN_INT
signal ss_in_neg : STD_LOGIC; -- SS_IN_N sampled with rising edge of clk
signal ss_in_pos : STD_LOGIC; -- SS_IN_N sampled with negative edge of clk
signal ss_n_out : STD_LOGIC_VECTOR(7 downto 0); -- output SS_N that are 3-stated if SS_IN_INT
-- is asserted indicating another master
--**************************** Component Definitions ********************************
-- 4-bit counter for bit counter
component upcnt4
port(
cnt_en : in STD_LOGIC; -- Count enable
clr : in STD_LOGIC; -- Active high clear
clk : in STD_LOGIC; -- Clock
qout : inout STD_LOGIC_VECTOR (3 downto 0)
);
end component;
begin
--************************** Bit Counter Instantiation ********************************
BIT_CNTR : upcnt4
port map(
cnt_en => bit_cnt_en,
clr => bit_cnt_reset,
clk => sck_int,
qout => bit_cnt
);
--************************** SS_IN_N Input synchronization *******************************
-- When the SS_IN_N input is asserted, it indicates that there is another master on the bus
-- that has selected this master as a slave. When this signal asserts, the SPI master needs
-- to reset and tristate outputs. Therefore, the SS_IN_N input should be synchronized with the
-- system clock to prevent glitches on this signal from reseting the SPI master. The proces
-- below first samples SS_IN_N with the rising edge of the system clock and the falling edge
-- of the system clock. If both of these samples show that the signal is asserted, then the
-- internal SS_IN_INT signal will assert. SS_IN_INT is passed to the uC logic to generate an
-- interrupt if interrupts have been enabled. It is also passed to the SCK logic and the
-- SPI Xmit shift register to tri-state the SCK and MOSI outputs.
ss_in_rising: process(clk, reset)
begin
if reset = RESET_ACTIVE then
ss_in_pos <= '1';
elsif clk'event and clk = '1' then
ss_in_pos <= ss_in_n;
end if;
end process;
ss_in_falling: process (clk, reset)
begin
if reset = RESET_ACTIVE then
ss_in_neg <= '1';
elsif clk'event and clk = '0' then
ss_in_neg <= ss_in_n;
end if;
end process;
ss_in_sample: process(clk,reset)
begin
if reset = RESET_ACTIVE then
ss_in_int <= '1';
elsif clk'event and clk = '1' then
if ss_in_pos = '0' and ss_in_neg = '0' then
ss_in_int <= '0';
else
ss_in_int <= '1';
end if;
end if;
end process;
--************************** Bit Counter reset ***************************************
-- The bit counter needs to be reset when the reset signal is asserted from the SPI control
-- state machine is asserted and when SS_IN_INT is asserted
-- is asserted
bit_cnt_reset <= RESET_ACTIVE when bit_cnt_rst = RESET_ACTIVE or ss_in_int = '0'
else not(RESET_ACTIVE);
--************************** SPI Control State Machine *******************************
-- Register process registers next state signals
-- Return to IDLE state whenever SS_IN_INT is asserted
spi_sm_reg:process(clk, reset, ss_in_int)
begin
-- Set state to IDLE upon reset
if (reset = RESET_ACTIVE or ss_in_int = '0') then
spi_state <= IDLE;
elsif clk'event and clk = '1' then
spi_state <= next_spi_state;
end if;
end process;
-- Combinatorial process determines next state logic
spi_sm_comb: process(spi_state, start,bit_cnt, sck_re, sck_fe, sck_int_re, sck_int_fe,
xmit_empty, cpha, cpol)
begin
-- set defaults
clk0_mask <= '0';
clk1_mask <= '0';
bit_cnt_en <= '0';
bit_cnt_rst <= RESET_ACTIVE;
next_spi_state <= spi_state;
done <= '0';
xmit_shift <= '0';
xmit_load <= '0';
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -