在2013年的工作中,涉及到了AM3359与XC7K325T之间的相互通信,其目的是为了获取FPGA设计版本号,该FPGA版本号保存在FPGA的寄存器0xFFFF中,FPGA的版本值随着加载程序发生变化,当时的版本信息为0x1003.
需要说明的是,在本文中的代码风格是刚工作两年的时候的代码风格,现在回看,这些代码风格实在难以阅读。尤其是SPI的verilog程序等。并不代表现在的编程水平与代码风格。
设计框图如下:
本文主要从三个方面介绍AM3359与FPGA的通讯
第一部分:SPI通信的基础定义
第二部分:AM335x的SPI通信编程
第三部分:FPGA从机SPI设计
SPI通信基础定义
通信是怎么发生
SPI接口是一种典型的全双工接口。通过同步时钟SCLK的脉冲将数据一位一位地在主机和从机之间交换。所以在开始通信之前,Master首先需要配置接口时钟,在Master配置时钟的时候,不需要通知从机它所配置的时钟频率具体是多少,设计人员只需要确保通讯频率是从机所支持的即可。
当Master通过片选信号(SS,低电平有效)选定一个Slave的时候,每向Slave发送一个周期的SCLK信号,都会有1bit的数据从MOSI引脚发送给Slave,Slave只需要在对应的引脚接收数据即可;同时,slave每收到一个周期的SCLK信号,都会从MISO想Master发送1bit的数据。
从上段描述中可以分析出一下两点:
1.无论Master还是Slave,都是按照bit来传输的,那么对于需要发送或者接收的数据,必须在Master或Slave中有一个移位寄存器,这些是由硬件来保证的,普通的SPI接口设计者不需要考虑移位寄存器的因素。
2.在通信中,Master发送数据后,一般需要保证Slave收到数据,这样才能确定数据在收发的过程中不发生因为硬件而导致的bit丢失。在SPI中,数据传输以“位交换”的方式传输,这样能根据从机返回的数据来确定从机已经收到数据了。SPI同样与其他基础通信方式(USB,I2C,UART等)一样无法确保传输数据的正确性。
SPI是一个相对比较开放的接口,具体表现在时钟极性/相位、帧大小、传输速度、LSB/MSB等规则没有一个确定的定义,需要根据不同的通信环境由设计开发者进行定义。
SPI的接口时序
在实际开发使用SPI的时候,需要注意使Master和Slave处于相同的Mode下工作。不同mode的定义主要是针对时钟的相关特性。
SCLK极性(CPOL):clock Polarity
SCLK相位(CPHA):clock Phase
CPOL
在解释CPOL之前先要介绍什么是SCLK的空闲时刻。在SPI通讯传输的时候,SCLK并不是时刻都有。在SCLK发送数据之前和发送数据之后,都会回到空闲状态,这个状态下,SCLK要么保持在高电平,要么保持在低电平。这个是需要设计者来指定的,CPOL的作用就是来指定SPI在IDLE状态下的点评状态。
- CPOL = 0 :时钟空闲状态(IDLE)的电平为低电平(0)。
- CPOL = 1 :时钟空闲状态(IDLE)的点评是高电平(1)。
CPHA
CPHA表示数据采样,数据有效的时刻。对应的数据采样是在第几个边沿进行采样。
- CPHA = 0 :在时钟第一个边沿采样。
-
- 对于CPOL = 0 :因为IDLE为低电平,那么第一个边沿就是从低电平到高电平,即为上升沿。
- 对于CPOL = 1 :因为IDLE为高电平,那么第一个边沿就是从高电平到低电平,即为下降沿。
- CPHA = 1 :在时钟第二个边沿采样。
-
- 对于CPOL = 0 :因为IDLE为低电平,那么第二个边沿就是从高电平到低电平,即为下降沿。
- 对于CPOL = 1 :因为IDLE为高电平,那么第二个边沿就是从低电平到高电平,即为上升沿。
需要注意的是:采样一定是需要先准备好数据,才用时钟的有效沿将数据打到对应的引脚上。
Mode选择参考
SPI没有一个通用的推荐模式,但是基于工程设计的时候是否有一个推荐的Mode选择呢?在CSDN博友的一篇《SPI接口扫盲 SPI定义/SPI时序(CPHA CPOL)》中,作者从功耗的角度分析,建议应该多选择SCLK在空闲状态下处于低电平,即CPOL保持在IDLE状态下为0。这是一个很好的分析方法。对于CPHA的选择分析,我更赞成根据实际的应用来做设计,而不是根据习惯来设计。