SPI 通信时序图
______________ ______________
| |--------SCK-------->| |
| |--------CS--------->| |
| MASTER | | SLAVE |
| |--------MOSI------->| |
| |<-------MISO--------| |
|______________| |______________|
基本组件
- MOSI (Master Out Slave In):主机发送数据到从机。
- MISO (Master In Slave Out):从机发送数据到主机。
- SCK (Serial Clock):由主机生成的时钟信号。
- SS/CS (Slave Select/Chip Select):用于选择从设备,低电平有效。
- 注:在3-line spi中用SDA引脚代替MOSI和MISO发送数据
多设备链接方式:常规SPI模式、菊花链模式
______________
| CS3|------------------->-----------+----------------------------------------------------------------
| CS2|------------------->-----------|---------------------------+------------------------------------
| CS1|------------------->---------- |---------------------------|---------------------------+--------
| MASTER | | | |
| SCLK|------------+------>-----------|---------+-----------------|---------+-----------------|--------
| MOSI|------------|--+--->-----------|---------|--+--------------|---------|--+--------------|--------
| MISO|<-----------|--|--+------------|---------|--|--+-----------|---------|--|--+-----------|--------
|______________| | | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | ______|______ | | | ______|______ | | | ______|______
| | | | CS | | | | | CS | | | | | CS |
+--|--|---->|CLK | +--|--|--->|CLK | +--|--|--->|CLK |
+--|---->|SDI | +--|--->|SDI | +--|--->|SDI |
| | SLAVE | | | SLAVE | | | SLAVE |
+----<|SDO | +---<|SDO | +---<|SDO |
|_____________| |_____________| |_____________|
______________
| CS|------------------->---------- +---------------------------+---------------------------+
| MASTER | | | |
| SCLK|------------+------>-----------|---------+-----------------|---------+ |
| MOSI|------------|--+ | | | | |
| MISO|<-----------|--|---------------|---------|-----------------|---------|-----------------|------------+
|______________| | | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | ______|______ | ______|______ | ______|______ |
| | | CS | | | CS | | | CS | |
+--|------->|CLK | +--------->|CLK | +--------->|CLK | |
+------->|SDI | +------>|SDI | +------>|SDI | |
| SLAVE | | | SLAVE | | | SLAVE | |
| SDO|>----+ | SDO|>----+ | SDO|>----+
|_____________| |_____________| |_____________|
解释
SS/CS 信号:
- 当
SS/CS
为低电平时,表示从设备被选中并开始通信。 - 当
SS/CS
变高时,通信结束,从设备停止响应。
- 当
SCK 信号:
- 主机生成时钟信号
SCK
,用于同步数据传输。 - 每个时钟周期可以传输一位数据。
- 数据在时钟的上升沿或下降沿采样,具体取决于 SPI 模式(Mode 0, 1, 2, 3)。
- 主机生成时钟信号
MOSI 和 MISO 信号:
- 在每个时钟周期内,
MOSI
和MISO
线上会传输一位数据。 - 数据通常以 MSB(最高有效位)先的方式传输。
MOSI
用于主机发送数据到从机。MISO
用于从机发送数据到主机。
- 在每个时钟周期内,
示例:8 位数据传输
假设我们传输一个字节(8 位),数据从高位到低位依次为 D7, D6, D5, D4, D3, D2, D1, D0
:
- 初始状态:
SS/CS
高电平,SCK
低电平,MOSI
和MISO
空闲。 - 激活从设备:
SS/CS
下降到低电平,从设备被选中。 - 数据传输:
- 第一个时钟周期(上升沿或下降沿,取决于模式):传输
D7
。 - 第二个时钟周期:传输
D6
。 - …
- 第八个时钟周期:传输
D0
。
- 第一个时钟周期(上升沿或下降沿,取决于模式):传输
- 完成传输:
SS/CS
上升到高电平,通信结束。
SPI中的同步方式(shift register同步)
// https://www.fpga4fun.com/SPI2.html
// sync SCK to the FPGA clock using a 3-bit shift register
reg [2:0] SCKr;
always @(posedge clk)
SCKr <= {SCKr[1:0], SCK}; // Shift in new SCK value on each clk posedge
wire SCK_risingedge = (SCKr[2:1]==2'b01); // Detect SCK rising edges
wire SCK_fallingedge = (SCKr[2:1]==2'b10); // Detect SCK falling edges
always @(posedge clk)
begin
if (~SSEL_active) // Check if chip select is active
bitcnt <= 3'b000;
else if (SCK_risingedge) // Only proceed if SCK has a rising edge
begin
bitcnt <= bitcnt + 3'b001; // Increment bit counter
// Implement a shift-left register (since we receive the data MSB first)
byte_data_received <= {byte_data_received[6:0], MOSI_data};
end
end
代码使用移位寄存器(如
SCKr
)可以方便地检测SCK
的上升沿和下降沿(一般要求clk需要比 SPI 总线上的SCK更快):SCKr[2:0]
是一个3位寄存器,每次在clk
的上升沿更新。SCKr[2:1] == 2'b01
表示SCK
从低电平变为高电平(上升沿)。SCKr[2:1] == 2'b10
表示SCK
从高电平变为低电平(下降沿)。
为什么使用3-bit shift register来同步SPI,而不直接使用
always @(posedge SCK ) begin … end
?- 通过使用移位寄存器同步
SCK
到 FPGA 的本地时钟域,不仅可以解决跨时钟域问题,还能可靠地检测边沿变化,提高系统的稳定性和可靠性。这种方法还简化了设计,使所有逻辑都能在一个统一的时钟域内工作。 - 直接在
SCK
上升沿触发写入数据,而在本地时钟读取数据,无法保证数据满足建立和保持时间的约束,导致次稳态发生,因此不推荐使用。 - shift register方法不仅能够可靠地检测边沿变化,还能过滤掉毛刺(glitches),因为需要连续两个周期保持一致的变化才能被识别为有效的边沿。
- 通过使用移位寄存器同步