Zynq中PL端SPI接口

2019-11-09 13:39:17 浏览数 (1)

SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议

SDO – 主设备数据输出,从设备数据输入 对应MOSI master output slave input

SDI – 主设备数据输入,从设备数据输出 对应MISO master input slave output

SCLK – 时钟信号,由主设备产生

CS – 从设备使能信号,由主设备控制,CS: 其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效,这就允许在同一总线上连接多个SPI设备成为可能。

通过控制CPOL和CPHA来控制采样边沿。

下面是SPI模式0,也就是数据在上升沿采样,在下降沿移出的简单程序。

-------------------------------------------------------------------------------

-- Copyright (c) 2010 Xilinx, Inc.

-- This design is confidential and proprietary of Xilinx, All Rights Reserved.

-------------------------------------------------------------------------------

-- ____ ____

-- / // /

-- /___/ / Vendor: Xilinx, Inc.

-- / Version: 1.00

-- Filename: SpiSerDes.vhd

-- / / Date Last Modified: October 25 2009

-- /___/ / Date Created: October 25 2009

-- /

-- ___/___

--

--Devices: Spartan-6, Virtex-5, Virtex-6, 7 series FPGAs

--Purpose: This module serializes and deserializes a byte's worth of

-- data to/from a SPI device for a master SPI controller.

--Description: This modules takes the following inputs:

-- inClk - Module clock and forwarded to SPI bus clk.

-- The frequency of this clock must be less than

-- or equal to the Fmax of the peripheral(s) on

-- the SPI bus.

-- inReset_EnableB - Active-high synchronous reset.

-- When High, resets this module and

-- also drives the SPI device chip-select High.

-- When Low, enables this module and

-- also drives SPI device chip-select Low.

-- inData8Send - The data byte to send to SPI device.

-- The input data byte is registered on the

-- first rising edge of inClk after

-- inStartTransfer transitions to High (and

-- when outTransferDone is High).

-- inStartTransfer - Start SPI serialization when this is High

-- and when outTransferDone=High.

-- This module has the following outputs:

-- outTransferDone - Signals when serialization is DONE.

-- Signal is driven Low on the first rising

-- edge of inClk after inStartTransfer

-- transitions to High.

-- Signal is returned to High after the module

-- has completed the serialization of a byte

-- of data.

-- outData8Receive - When outTransferDone=High, this output has

-- the data byte received from the inSpiMiso

-- pin during the serial transfer process.

-- This module is the master controller for SPI bus signals:

-- outSpiCsB - Connect to SPI device active-low chip select

-- outSpiClk - Connect to SPI bus clk

-- outSpiMosi - Connect to SPI bus master-out, slave-input

-- inSpiMiso - Connect to SPI bus master-in, slave-output

-- If another device can be a master of the SPI bus, then use

-- outSpiCsB as the active-Low output enable control signal for

-- all SPI bus outputs. When using outSpiCsB as an output enable,

-- all controlled outputs must have a pull-up, especially the SPI

-- chip-select signal.

--Usage: Module setup:

-- - Connect for SPI ports to SPI bus. See above.

-- - Supply inClk. Fmax determined by target (slave) SPI device.

-- Module use sequence:

-- 1. Reset module:

-- 1.A. Drive inReset_EnableB=High to reset module

-- 2. Enable SPI device (SPI CSB=Low)

-- 2.A. Drive inReset_enableB=Low to select target SPI device.

-- 3. Serialize byte output via MOSI and byte input via MISO:

-- 3.A. For each byte:

-- 3.A.1: Start serialization:

-- inData8Send <= byte to send

-- inStartTransfer <= High

-- 3.A.2: Wait for serialization DONE

-- Wait for outTransferDone=High

-- Get parallel MISO data from outData8Receive

-- 4. Disable SPI device (SPI CSB=High)

-- 4.A. Drive inReset_EnableB=High

-- NOTES:

-- - All signals active/transition on rising-edge inClk except

-- outSpiMosi transitions on falling-edge of outSpiClk.

-- - If inStartTransfer=High when outTransferDone=High, then

-- next byte serialization starts on following rising inClk.

-- To prevent next byte serialization, set inStartTransfer=Low

-- before outTransferDone goes High.

-- - outSpiClk runs at same frequency and phase as inClk.

-- outSpiClk is gated.

--Signal Timing:

-- _ _ _ _ _ _ _ _ _

-- inClk _/ _/ _/ _/ _/ _/ ....._/ _/ _/ _

-- ___ _____

-- inReset_EnableB _________________________________/

-- _____ ___

-- outSpiCsB _________________________________/

-- ___________________________________

-- inStartTransfer _______/ \\\\\\\\\\\\*\\\

-- _________ ___________

-- outTransferDone ______________.....__/

-- _______ ___

-- inData8Send[7:0] _______XD8SXXX...

-- ___ ___ ___ ___ _________

-- inSpiMosi XD7_XD6_XD5_X.....XD0_X_________

-- ___________ _ _ _ _ ___________

-- outSpiClk _/ _/ _/ ....._/

-- ___________

--outData8Receive[7:0] XD8SX XXXD8R*D8SX___

-- *Note: if inStartTransfer=High, then inData8Send loaded into outData8Receive

--Reference:

--Revision History:

-- Revision (YYYY/MM/DD) - [User] Description

-- Rev 1.00 (2009/10/25) - [RMK] Created.

-------------------------------------------------------------------------------

library ieee;

--Library UNISIM;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

use ieee.numeric_std.all;

--use UNISIM.vcomponents.all;

entity SpiSerDes is

port

(

-- SerDes clock and control signals

inClk : in std_logic; -- System clock. Fmax <= SPI peripheral Fmax.

inReset_EnableB : in std_logic; -- Active-high, synchronous reset.

inStartTransfer : in std_logic; -- Active-high, initiate transfer of data

outTransferDone : out std_logic; -- DONE='1' when transfer is done

-- Parallel data ports

inData8Send : in std_logic_vector(7 downto 0); -- Sent to SPI device

outData8Receive : out std_logic_vector(7 downto 0); -- Received from SPI device

-- SPI ports and tristate control - Connect these to the SPI bus

outSpiCsB : out std_logic; -- SPI chip-select to SPI device

-- or all SPI outputs control enable

outSpiClk : out std_logic; -- SPI clock to SPI device

outSpiMosi : out std_logic; -- SPI master-out, slave-in to SPI device

inSpiMiso : in std_logic -- SPI master-in, slave-out from SPI device

);

end SpiSerDes;

architecture behavioral of SpiSerDes is

-- Constants

constant cShiftCountInit : std_logic_vector(8 downto 0) := B"000000001";

-- Registers

signal regShiftCount : std_logic_vector(8 downto 0) := cShiftCountInit;

signal regShiftData : std_logic_vector(7 downto 0) := B"00000000";

signal regSpiCsB : std_logic := '1';

signal regSpiMosi : std_logic := '1';

signal regTransferDoneDelayed : std_logic := '1';

-- Signals

signal intTransferDone : std_logic;

-- Attributes

attribute clock_signal : string;

attribute clock_signal of inClk : signal is "yes";

begin

-- Internal signals

intTransferDone <= regShiftCount(0);

-- TransferDone delayed by half clock cycle

processTransferDone : process (inClk)

begin

if (falling_edge(inClk)) then

regTransferDoneDelayed <= intTransferDone;

end if;

end process processTransferDone;

-- SPI chip-select (active-Low) is always inverse of inReset_EnableB.

processSpiCsB : process (inClk)

begin

if (rising_edge(inClk)) then

regSpiCsB <= inReset_EnableB;

end if;

end process processSpiCsB;

-- Track transfer of serial data with barrel shifter.

processShiftCount : process (inClk)

begin

if (rising_edge(inClk)) then

if (inReset_EnableB='1') then

regShiftCount <= cShiftCountInit;

elsif ((intTransferDone='0') or (inStartTransfer='1')) then

-- Barrel shift (rotate right)

regShiftCount <= regShiftCount(0) & regShiftCount(8 downto 1);

end if;

end if;

end process processShiftCount;

-- Simultaneous serialize outgoing data & deserialize incoming data. MSB first

processShiftData : process (inClk)

begin

if (rising_edge(inClk)) then

if (intTransferDone='0') then

-- SHIFT-left while not outTransferDone

regShiftData <= regShiftData(6 downto 0) & inSpiMiso;

elsif (inStartTransfer='1') then

-- Load data to start a new transfer sequence from a done state

regShiftData <= inData8Send;

end if;

end if;

end process processShiftData;

-- SPI MOSI register outputs on falling edge of inClk. MSB first.

processSpiMosi : process (inClk)

begin

if (falling_edge(inClk)) then

if (inReset_EnableB='1') then

regSpiMosi <= '1';

elsif (intTransferDone='0') then

regSpiMosi <= regShiftData(7);

end if;

end if;

end process processSpiMosi;

-- Assign outputs

outSpiClk <= (inClk or intTransferDone or regTransferDoneDelayed);

outSpiCsB <= regSpiCsB;

outSpiMosi <= regSpiMosi;

outTransferDone <= intTransferDone;

outData8Receive <= regShiftData;

end behavioral;

0 人点赞