SPI,全称(Serial Peripheral interface)是由摩托罗拉公司首先定义的协议,中文名为串型外围设备接口。SPI是一种高速全双工的总线协议
Serial(串型):与并型相对应,单向数据通路只需要一根线,而同样常见的AMBA则为并型总线
Peripheral(外围):指此总线多用来连接如“AD转换、EEPROM、PWM”等外围设备,即对应于AMBA的APB部分
Interface(总线接口):很好理解,不再赘述。
通信协议可以按照通信方式分为单工,半双工,全双工三种。
单工:发射端和接收端固定,有一条数据通路,通路上数据单向流动。
半双工:发射端和接收端可变,有一条数据通路,通路上数据双向流动。
全双工:发射端和接收端,有两条数据通路,一条从TX到RX,另一条从RX到TX。
一张形象的图片表示如下
比如说我们在从零开始的Verilog UART设计中所实现的就是一个单工UART
因为SPI是全双工总线协议,因此SPI的数据通路上存在从主设备到从设备的数据通道和从从设备到主设备的数据通道
SPI需要四条线才能完成数据的发送,分为3条总线和1条片选线
SCK:Serial Clock, 串行时钟信号,SPI需要依靠着这个信号的边沿进行数据的传递
MOSI:Master output Slave input,对于主设备来说,是发送数据的端口,对于从设备来说,是接收数据的端口。
MISO:Master input Slave output,对于从设备来说,是接收数据的端口,对于主设备来说,是发送数据的端口。
NSS: N Slave connect,一般情况下是由主机发送,从机接收,表示哪一个从设备有效的信号
因为MOSI和MISO的存在,因此SPI才是一个全双工的协议(即分别对于主设备和从设备来说,既可以发送数据,又可以接收数据)
根据从设备之间是否存在联系,我们可以将SPI的连接方式分为“多NSS形式”和”菊花链形式”。
SPI的第一种连接方式是“多NSS形式”的连接,比如说从设备1是一个AD转换模块,从设备2是一个比较器,设备3是一块液晶,他们之间没有联系,主设备需要操控哪个从设备,就拉低对应NSS上面的信号,使能从设备进行数据转换
SPI协议的第二种形式是菊花链的形式,比如说从设备1是一块EEPROM,从设备2是一个DSP,从设备3是一个比较器,三个从设备之间存在联系,当来自主设备的地址信号到来时,先从EEPROM中读出数据,数据放到DSP中进行处理,处理后的数据,最终在从设备3中进行比较
时钟极性(CPOL)指通讯设备处于空闲状态(SPI开始通讯前、nSS线无效)时,SCK的状态。
CPOL | 对应电平 |
---|---|
0 | SCK在空闲时为低电平 |
1 | SCK在空闲时为高电平 |
这里的CPOL实际上对应于状态机IDLE状态时的SCK的值是0是1,即三段式状态机IDLE时的输出
时钟相位(CPHA)指数据的采样时刻位于SCK的偶数边沿采样还是奇数边沿采样。
CPHA | 对应电平 |
---|---|
0 | MOSI或MISO数据线上的信号在“奇数边沿”被采样 |
1 | MOSI或MISO数据线上的信号在”偶数边沿”被采样 |
举例:假如CPOL = 0时,CPHA=0,对应1,3,5处采样,即为上升沿采样,CPHA=1,对应2,4,6处采样,即为下降沿采样。
这里的CPHA也同样能在状态机的跳变中得到体现,即对应某些状态的采样行为
根据这个图,我们可以发现
Case1:CPOL=0, CPHA=0
Case2:CPOL=1, CPHA=1,Case1和Case2都对应上升沿触发
Case3:CPOL=0, CPHA=1
Case4:CPOL=1, CPHA=0,Case3和Case4都对应下降沿触发
为了保证采样的时候数据稳定,我们还需要做些什么?
我们需要保证采样的时候数据是稳定的,才不会发生建立时间和保持时间的违例,因此,当我们在上升沿的时候进行采样,我们可以在前一个相差半个时钟周期的下降沿,切换数据。
同样,当我们在下降沿的时候进行采样,我们也可以在前一个相差半个时钟周期的上升沿,切换数据,以此来保证采样时的数据稳定性。
有一张非常形象的图片来形容SPI的数据发送与接收,即每当Master发送一位数据的时候,他还会接收到一位数据,因此对于SPI来说,数据传输的本质其实是两个寄存器的移位操作,寄存器的位宽,就是我们所说的数据大小,一般情况下,SPI的数据大小是一个字节或者两个字节(8位或16位)
图片引用自《SPI Block Guide, motorola Inc,14 JUL 2004》
对于全局时钟来讲,频率可能会很高,比如常见的CPU是GHz级别,常见的MCU也有近百MHz级别,但是对于所连接的外设,受限于建立时间和保持时间的限制,可能没有办法跑到MCU主频的级别,因此我们可能需要波特率分频系数来对高速全局时钟进行处理,以此来确保不发生data的violation。
参考作者之前的文章,我们可以获知分频电路的设计方法
【数字IC手撕代码】Verilog奇数分频|题目|原理|设计|仿真
【数字IC手撕代码】Verilog偶数分频|题目|原理|设计|仿真
【数字IC手撕代码】Verilog半整数分频|题目|原理|设计|仿真
【数字IC手撕代码】Verilog小数分频|题目|原理|设计|仿真
以上参数可以保证SPI的基本功能,但一个更为完善的SPI当然不仅限于以上参数,以下参数仅作基本梳理,感兴趣的同学可自行了解相关内容。
SPI_FirstBit,决定SPI是MSB还是LSB的传输形式
SPI_CRCPolynomial,决定SPI是否采用CRC校验的形式进行数据传输
SPI_Direction; 传输方向,两向全双工或单向接收
接下来的文章,我们将从零开始使用Verilog设计一个SPI出来,并进行不那么充分的验证工作,其中SPI具体满足的参数如下