第二篇:SPI控制器FPGA架构设计
聚焦模块化设计、时序优化与资源管理
1. 系统级架构设计
1.1 模块化硬件架构
verilog
module spi_controller (
input wire clk, // 系统时钟 (100 MHz)
input wire rst_n, // 异步复位
// 配置接口
input wire [15:0] clk_div, // 时钟分频系数
input wire [1:0] spi_mode, // CPOL/CPHA模式
input wire lsb_first, // 位传输顺序
// 数据接口
input wire [7:0] tx_data, // 发送数据
output reg [7:0] rx_data, // 接收数据
output reg busy, // 传输状态
// SPI物理接口
output wire sck, // SPI时钟
output wire mosi, // 主出从入
input wire miso, // 主入从出
output wire cs_n // 片选 (低有效)
);
// 核心子模块实例化
clock_gen u_clk_gen(.*); // 时钟生成
fsm_controller u_fsm(.*); // 状态机
data_path u_datapath(.*); // 数据路径
cs_decoder u_cs_dec(.*); // 片选译码
endmodule
关键模块说明 :
- 时钟域划分 :
高速域 (clk) :配置寄存器访问 (100MHz)
SPI域 (spi_clk) :SCK同步逻辑 (≤50MHz)
跨时钟域同步 :TX/RX数据通过异步FIFO交换
1.2 寄存器映射表
地址偏移 | 寄存器名 | 位定义 | 功能 |
---|---|---|---|
0x00 | CTRL | [0]:使能 [1]:LSB [3:2]:模式 | 控制寄存器 |
0x04 | CLK_DIV | 16位分频系数 | 时钟分频 |
0x08 | TX_DATA | 8位发送数据 | 发送缓冲区 |
0x0C | RX_DATA | 8位接收数据 | 接收缓冲区 |
0x10 | STATUS | [0]:忙 [1]:传输完成 | 状态寄存器 |
2. 时钟生成电路
2.1 可编程分频器设计
verilog
module clock_gen (
input wire clk,
input wire [15:0] div_value,
output reg spi_clk
);
reg [15:0] counter = 0;
reg clk_phase = 0; // 相位控制
always @(posedge clk) begin
if (counter >= div_value) begin
counter <= 0;
clk_phase <= ~clk_phase; // 翻转相位
end else begin
counter <= counter + 1;
end
end
// CPOL控制输出极性
assign sck = (spi_mode[1]) ? ~clk_phase : clk_phase;
endmodule
关键技术 :
-
小数分频实现 :通过累加器实现N.5分频(如3.5分频)
verilogreg [3:0] acc = 0; always @(posedge clk) begin acc <= acc + 4'd2; // 步进值=2 (2/4=0.5) spi_clk <= (acc < 4'd4); // 50%占空比 end
-
动态时钟切换 :CPOL变化时插入死区时间避免毛刺
verilogalways @(posedge clk) begin if (mode_changed) begin sck <= 1'bz; // 高阻态保持10ns #10; sck <= new_polarity; // 应用新极性 end end
3. 核心状态机设计
3.1 状态转移图

3.2 Verilog实现
verilog
typedef enum {IDLE, START, TX_RX, STOP} spi_state;
spi_state current_state = IDLE;
reg [2:0] bit_cnt = 0; // 位计数器
always @(posedge spi_clk) begin
case(current_state)
IDLE:
if (cs_active) begin
current_state <= START;
sck <= 1'b0; // Mode 0初始化
end
START:
current_state <= TX_RX;
TX_RX:
if (bit_cnt == 7)
current_state <= STOP;
else
bit_cnt <= bit_cnt + 1;
STOP:
if (!cs_hold)
current_state <= IDLE;
endcase
end
关键特性 :
-
CPHA自适应 :通过状态机控制采样沿
verilog// CPHA=0: 上升沿采样,下降沿切换数据 wire sample_edge = (spi_mode[0]) ? negedge sck : posedge sck; wire shift_edge = (spi_mode[0]) ? posedge sck : negedge sck;
-
连续传输支持 :
cs_hold
信号保持状态机在STOP状态
4. 数据路径优化
4.1 双缓冲机制
verilog
reg [7:0] tx_buffer, tx_shift;
reg [7:0] rx_shift, rx_buffer;
// 发送双缓冲
always @(posedge clk) begin
if (!busy)
tx_shift <= tx_buffer; // 空闲时加载新数据
end
// 接收双缓冲
always @(posedge spi_clk) begin
if (bit_cnt == 0 && current_state == TX_RX)
rx_buffer <= rx_shift; // 传输完成锁存数据
end
4.2 循环移位寄存器
verilog
// LSB优先传输实现
always @(shift_edge) begin
if (current_state == TX_RX) begin
tx_shift <= lsb_first ?
{1'b0, tx_shift[7:1]} :
{tx_shift[6:0], 1'b0};
rx_shift <= lsb_first ?
{miso, rx_shift[7:1]} :
{rx_shift[6:0], miso};
end
end
4.3 多从机数据隔离
verilog
// 基于CS的三态控制
assign mosi = (cs_active) ? tx_shift[7] : 1'bz;
assign miso = (cs_active) ? slave_miso : 1'bz;
// 从设备选择译码
module cs_decoder (
input wire [3:0] slave_sel, // 4位从机选择
output reg [7:0] cs_n // 8个CS信号
);
always @(*) begin
cs_n = 8'hFF; // 默认全关
if (slave_sel < 8)
cs_n[slave_sel] = 1'b0; // 激活选中从机
end
endmodule
5. 时序收敛关键策略
5.1 多周期路径约束
tcl
# XDC约束示例 (Vivado)
set_multicycle_path 2 -setup -from [get_clocks clk] -to [get_clocks spi_clk]
set_multicycle_path 1 -hold -end
5.2 跨时钟域同步链
verilog
// 异步信号三级同步
reg [2:0] sync_miso;
always @(posedge spi_clk) begin
sync_miso <= {sync_miso[1:0], miso};
end
5.3 关键路径流水化
verilog
// 添加流水线提升时序
always @(posedge spi_clk) begin
// 第1拍:计算下一状态
next_state <= fsm_logic(current_state);
// 第2拍:更新状态
current_state <= next_state;
end
6. 资源优化技术
6.1 动态部分重配置(Xilinx FPGA)
tcl
# 重配置命令(切换SPI模式)
write_cfgmem -format BIN -interface SPIx4 -size 8 -loadbit "up 0x0 new_mode.bin"
6.2 引脚复用技术
复用方案 | 实现方式 | 节省IO |
---|---|---|
QSPI模式 | 将WP/HOLD引脚用作数据线 | 2根 |
三线SPI | MOSI/MISO共享SIO线 | 1根 |
分时复用 | 用同一组引脚驱动多组SPI外设 | 50% |
附录:Artix-7资源占用报告
模块 | LUTs | FFs | 最大频率 | 功耗 |
---|---|---|---|---|
时钟生成器 | 42 | 32 | 450 MHz | 8 mW |
状态机 | 78 | 64 | 350 MHz | 12 mW |
数据路径 | 105 | 80 | 400 MHz | 15 mW |
总计 | 225 | 176 | 350 MHz | 35 mW |