LUT优化与SPI通信协同降低刷新延迟的工程实践 - 第3节
3.1 SPI 总线架构与信号定义
SPI(Serial Peripheral Interface)是一种同步、全双工、主从架构的串行通信协议,由 Motorola 公司在 20 世纪 80 年代提出。在 FPGA 与嵌入式系统中,SPI 因其极低的引脚占用(通常 4 线)和可编程的时钟速率,成为连接 ADC、DAC、传感器、存储器以及显示驱动器的首选接口之一。
3.1.1 四线制信号定义
| 信号名称 | 缩写 | 方向(主→从) | 功能描述 |
|---|---|---|---|
| 串行时钟 | SCLK / SCK | 主→从 | 由主设备产生,决定数据传输速率;每个时钟周期传输 1 bit |
| 主出从入 | MOSI | 主→从 | 主设备发送数据至从设备的数据线 |
| 主入从出 | MISO | 从→主 | 从设备发送数据至主设备的数据线 |
| 片选 | CS / SS | 主→从 | 低电平有效;主设备通过拉低 CS 选中目标从设备,开始通信 |
工程提示:在 FPGA 设计中,SCLK 通常由系统时钟分频产生,分频系数决定了 SPI 速率。对于高刷新率应用(如 240 Hz 显示屏),SCLK 频率应尽可能接近 FPGA 时序约束允许的上限,但需保证从设备时序余量 ≥ 2 ns。
3.1.2 SPI 总线拓扑结构
SPI 支持两种拓扑:独立片选(每个从设备独占一根 CS 线)和菊花链(共享 SCLK/MOSI,数据逐级传递)。在 LUT 优化场景中,独立片选更常见,因为菊花链会引入额外的传播延迟。
上图展示了典型的一主三从独立片选拓扑。主设备(FPGA)通过独立的 CS 线选择目标从设备,共享 SCLK、MOSI 和 MISO 总线。这种结构在 LUT 优化中便于通过状态机快速切换片选,减少总线空闲时间。
3.2 时钟极性与相位(CPOL & CPHA)
SPI 协议通过 时钟极性(CPOL) 和 时钟相位(CPHA) 定义四种工作模式。CPOL 决定 SCLK 空闲电平,CPHA 决定数据采样沿。FPGA 工程师必须根据从设备数据手册精确配置这两个参数,否则会导致数据错位。
3.2.1 四种模式定义
| 模式 | CPOL | CPHA | 空闲时钟电平 | 数据采样沿 | 数据输出沿 |
|---|---|---|---|---|---|
| 模式 0 | 0 | 0 | 低电平 | 上升沿 | 下降沿 |
| 模式 1 | 0 | 1 | 低电平 | 下降沿 | 上升沿 |
| 模式 2 | 1 | 0 | 高电平 | 下降沿 | 上升沿 |
| 模式 3 | 1 | 1 | 高电平 | 上升沿 | 下降沿 |
关键记忆法:CPHA=0 时数据在第一个时钟沿采样(上升沿或下降沿取决于 CPOL);CPHA=1 时数据在第二个时钟沿采样。多数 SPI 显示驱动器和 ADC 默认使用模式 0(CPOL=0, CPHA=0)。
3.2.2 时序波形对比
常见错误:在 FPGA 中,如果 SPI 时钟由 PLL 产生且相位未对齐,可能导致采样沿与数据输出沿重叠,造成亚稳态。建议在 RTL 代码中显式例化
IDDR 或 ODDR 原语来保证沿对齐。
3.3 全双工通信机制
SPI 的全双工特性意味着在每个 SCLK 周期内,主设备通过 MOSI 发送一位数据,同时从设备通过 MISO 返回一位数据。这种“一发一收”的对称结构使得 SPI 在吞吐量上优于 I²C(半双工)和 UART(异步全双工但需波特率匹配)。
3.3.1 全双工数据流模型
3.3.2 全双工 vs 半双工对比
| 特性 | SPI(全双工) | I²C(半双工) | UART(全双工异步) |
|---|---|---|---|
| 数据线数量 | 2(MOSI + MISO) | 1(SDA 双向) | 2(TX + RX) |
| 时钟线 | 独立 SCLK | 独立 SCL | 无(异步) |
| 每时钟传输 bit 数 | 2(1 发 + 1 收) | 1(半双工切换) | 1(需起始/停止位) |
| 典型吞吐率(10 MHz) | 10 Mbit/s 双向 | ~3.4 Mbit/s(高速模式) | ~1 Mbit/s(受波特率限制) |
| FPGA 资源消耗 | 低(无仲裁逻辑) | 中(需状态机处理 ACK) | 低(但需波特率发生器) |
工程实践:在 LUT 优化中,SPI 的全双工特性允许我们利用“发送即接收”的机制——例如向显示驱动器发送像素数据的同时,读取其状态寄存器,无需额外通信周期。这在高刷新率场景下可节省约 30% 的总线占用时间。
3.3.3 FPGA 全双工 SPI 核心代码片段
以下 Verilog 代码展示了全双工 SPI 主设备的核心移位逻辑。注意 mosi_out 和 miso_in 在同一时钟沿操作,实现真正的全双工。
// SPI 主设备全双工移位寄存器(模式 0)
module spi_master_full_duplex (
input wire clk, // 系统时钟
input wire rst_n, // 异步复位
input wire start, // 启动传输
input wire [7:0] tx_data, // 待发送数据
output reg [7:0] rx_data, // 接收数据
output reg busy, // 忙标志
output reg sclk, // SPI 时钟
output reg mosi, // 主出从入
input wire miso // 主入从出
);
reg [3:0] bit_cnt; // 位计数器
reg [7:0] shift_reg; // 移位寄存器
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
sclk <= 1'b0;
mosi <= 1'b0;
busy <= 1'b0;
bit_cnt <= 4'd0;
shift_reg <= 8'd0;
rx_data <= 8'd0;
end else begin
if (start && !busy) begin
busy <= 1'b1;
bit_cnt <= 4'd0;
shift_reg <= tx_data;
end else if (busy) begin
// SCLK 上升沿:主设备发送数据(MOSI 更新)
if (sclk == 1'b0) begin
sclk <= 1'b1;
mosi <= shift_reg[7]; // 发送最高位
end else begin
// SCLK 下降沿:主设备采样 MISO,同时移位
sclk <= 1'b0;
shift_reg <= {shift_reg[6:0], miso}; // 左移并捕获 MISO
bit_cnt <= bit_cnt + 1'b1;
if (bit_cnt == 4'd7) begin
busy <= 1'b0;
rx_data <= {shift_reg[6:0], miso}; // 完成接收
end
end
end
end
end
endmodule
代码要点:
- 在 SCLK 上升沿更新 MOSI(发送),下降沿采样 MISO(接收),符合模式 0 时序。
- 移位寄存器在下降沿左移,同时将 MISO 移入最低位,实现“边发边收”。
- 8 个时钟周期后,
rx_data自动包含从设备返回的完整字节。
3.4 SPI 通信时序关键参数
在 FPGA 工程中,除了协议逻辑,还需关注以下时序参数以确保可靠通信: