⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi_control_sm.vhd

📁 SPI.zip
💻 VHD
📖 第 1 页 / 共 2 页
字号:
-- 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 + -