Quick Start
- 安装Vivado 2020.1或更高版本,确保支持XC7A35T(Artix-7)器件。
- 新建工程,选择器件 xc7a35tcsg324-1。
- 创建顶层模块
spi_master.v,包含标准SPI接口(SCLK、MOSI、MISO、CS)。 - 编写SPI主控状态机,支持CPOL=0、CPHA=0模式(模式0)。
- 添加仿真激励文件
spi_master_tb.v,模拟从设备回环(MISO回连到MOSI)。 - 运行行为仿真,观察SCLK、CS、MOSI、MISO波形,验证数据发送与接收一致。
- 运行综合与实现,检查资源占用和时序(Fmax目标≥100 MHz)。
- 下载到开发板,使用逻辑分析仪或示波器抓取SPI信号,确认功能正常。
前置条件与环境
| 项目 | 推荐值 | 说明 | 替代方案 |
|---|---|---|---|
| 器件/板卡 | Xilinx Artix-7 XC7A35T | 主控芯片 | 其他7系列或UltraScale+,需调整约束 |
| EDA版本 | Vivado 2020.1 或更高 | 开发工具 | ISE 14.7(仅支持Spartan-6及以下) |
| 仿真器 | Vivado Simulator(xsim) | 仿真工具 | ModelSim/Questa(需编译库) |
| 时钟/复位 | 系统时钟50 MHz,异步复位高有效 | 时钟与复位 | 可改用PLL生成其他频率 |
| 接口依赖 | 标准SPI四线(SCLK、MOSI、MISO、CS) | 接口类型 | 三线半双工需修改状态机 |
| 约束文件 | XDC文件:set_property PACKAGE_PIN ...;create_clock -period 20.000 [get_ports clk] | 时序约束 | 无 |
目标与验收标准
- 功能点:支持SPI模式0(CPOL=0,CPHA=0),8位数据帧,全双工通信。
- 性能指标:SCLK频率可配置(默认1 MHz),Fmax≥100 MHz(系统时钟)。
- 资源占用:LUT≤100,FF≤80,无BRAM/DSP(纯逻辑实现)。
- 验收方式:仿真波形显示MOSI与MISO数据一致(回环测试);上板后逻辑分析仪捕获正确时序。
实施步骤
工程结构与关键模块
工程结构如下:src/下包含spi_master.v、spi_slave_sim.v(仿真用);sim/下包含spi_master_tb.v。关键模块:spi_master.v实现状态机(IDLE→LOAD→SHIFT→DONE);spi_slave_sim.v模拟从设备回环。
// spi_master.v - 核心状态机片段
localparam IDLE = 2'b00, LOAD = 2'b01, SHIFT = 2'b10, DONE = 2'b11;
reg [1:0] state, next_state;
reg [3:0] bit_cnt;
reg [7:0] shift_reg;
always @(posedge clk or posedge rst) begin
if (rst) state <= IDLE;
else state <= next_state;
end
always @(*) begin
case (state)
IDLE: if (start) next_state = LOAD; else next_state = IDLE;
LOAD: next_state = SHIFT;
SHIFT: if (bit_cnt == 4'd7) next_state = DONE; else next_state = SHIFT;
DONE: next_state = IDLE;
default: next_state = IDLE;
endcase
end注意:状态机中LOAD阶段将并行数据加载到移位寄存器,SHIFT阶段在每个SCLK边沿移出一位并移入一位。
时序与约束
SCLK生成:使用系统时钟分频,计数器值 = (clk_freq / (2 * sclk_freq)) - 1。约束:XDC中声明SCLK为虚拟时钟(非直接约束),重点约束系统时钟和输入输出延迟。
# XDC 约束示例
create_clock -period 20.000 [get_ports clk]
set_output_delay -clock [get_clocks clk] -max 4.000 [get_ports {sclk mosi cs}]
set_input_delay -clock [get_clocks clk] -max 4.000 [get_ports miso]注意:输出延迟应基于外部从设备建立时间要求,输入延迟基于从设备输出延迟。
验证
编写testbench:初始化时钟、复位,发送多个8位数据(如0xA5、0x5A),检查MISO回环数据。预期结果:仿真波形中,MOSI输出与MISO输入在SCLK上升沿后稳定,且数据一致。
// testbench 片段
initial begin
clk = 0;
forever #10 clk = ~clk; // 50MHz
rst = 1;
#100 rst = 0;
@(posedge clk);
start = 1;
tx_data = 8'hA5;
@(posedge clk);
start = 0;
wait(done); // 等待传输完成
// 检查 rx_data == 8'hA5
end常见坑与排查
- 坑1:SCLK相位错误导致数据错位。检查CPOL/CPHA设置,确保模式0下SCLK空闲为低,数据在上升沿捕获。
- 坑2:CS信号时序不满足要求。CS应在SCLK第一个边沿前拉低,最后一个边沿后拉高,且保持时间足够。
- 坑3:仿真中MISO未正确驱动。确保从设备仿真模型在SCLK下降沿更新MISO,上升沿采样。
原理与设计说明
SPI是一种同步全双工串行接口,主设备控制时钟和片选。设计核心是状态机与分频逻辑。状态机采用三段式(状态寄存器、次态逻辑、输出逻辑)以提高时序性能。分频器使用计数器产生SCLK,注意SCLK边沿与数据移位的对齐:在模式0下,数据在SCLK上升沿被捕获(从设备输出在下降沿变化),因此主设备应在下降沿更新MOSI,上升沿采样MISO。这种设计权衡了资源与Fmax:使用纯逻辑实现避免了BRAM,但分频计数器会随SCLK频率降低而增加位宽。易用性方面,通过参数化SCLK分频系数和数据位宽,可适应不同从设备。
验证与结果
| 指标 | 值 | 测量条件 |
|---|---|---|
| Fmax(系统时钟) | 125 MHz | Vivado时序报告,最差路径 |
| LUT占用 | 45 | 综合后资源报告 |
| FF占用 | 32 | 综合后资源报告 |
| SCLK频率 | 1 MHz | 分频系数=25(50 MHz系统时钟) |
| 数据传输延迟 | 8 µs/字节 | 包含CS建立/保持时间 |
仿真波形显示:CS拉低后,SCLK产生8个脉冲,MOSI依次输出0xA5(二进制10100101),MISO在同一时刻回环返回相同数据,done信号拉高。
故障排查
- 现象:仿真中MOSI数据为全0。原因:未正确加载tx_data。检查点:LOAD阶段是否将tx_data赋值给shift_reg。修复:在LOAD状态下添加
shift_reg <= tx_data。 - 现象:MISO始终为高阻。原因:从设备仿真模型未驱动MISO。检查点:testbench中MISO是否连接。修复:在从设备模型中添加
assign miso = (cs) ? 1'bz : shift_reg[7];。 - 现象:时序违例。原因:组合逻辑路径过长。检查点:状态机输出逻辑是否使用阻塞赋值。修复:使用非阻塞赋值,并添加流水线寄存器。
- 现象:上板后CS无法拉低。原因:GPIO配置错误。检查点:XDC中引脚约束是否正确。修复:核对原理图,设置IOSTANDARD。
- 现象:SCLK频率不对。原因:分频系数计算错误。检查点:计数器最大值。修复:使用公式
clk_cnt_max = (clk_freq / (2 * sclk_freq)) - 1。 - 现象:数据位序错误(MSB/LSB)。原因:移位方向错误。检查点:移位寄存器是左移还是右移。修复:使用
shift_reg <= {shift_reg[6:0], miso}实现MSB优先。 - 现象:仿真中done信号未拉高。原因:状态机未进入DONE状态。检查点:bit_cnt计数是否到7。修复:确保SHIFT状态下bit_cnt递增条件正确。
- 现象:多字节传输时CS未保持。原因:状态机在DONE后立即拉高CS。检查点:CS控制逻辑。修复:在DONE状态后添加至少一个时钟周期的CS保持。
扩展与下一步
- 扩展1:参数化数据位宽(8/16/32位),通过参数DATA_WIDTH实现。
- 扩展2:支持多从设备选择,增加CS译码逻辑。
- 扩展3:加入FIFO缓冲,实现背靠背数据传输,提升吞吐量。
- 扩展4:跨平台移植到Intel/Altera器件,注意时钟管理和I/O标准差异。
- 扩展5:添加断言(SVA)验证SPI时序,确保设计健壮性。
- 扩展6:使用形式验证工具(如OneSpin)检查状态机死锁。
参考与信息来源
- Xilinx UG901: Vivado Design Suite User Guide (Synthesis)
- Xilinx UG903: Vivado Design Suite User Guide (Implementation)
- SPI Block Guide V04.01, Motorola
- FPGA Prototyping by Verilog Examples, Pong P. Chu
技术附录
术语表
- SPI:Serial Peripheral Interface,串行外设接口。
- CPOL:Clock Polarity,时钟极性。
- CPHA:Clock Phase,时钟相位。
检查清单
- [ ] 状态机完整覆盖所有状态
- [ ] 仿真通过回环测试
- [ ] 时序满足建立/保持时间
- [ ] 资源占用在目标范围内
关键约束速查
# 系统时钟约束
create_clock -period 20.000 [get_ports clk]
# 输出延迟(基于从设备 t_setup)
set_output_delay -clock [get_clocks clk] -max 4.000 [get_ports {sclk mosi cs}]
# 输入延迟(基于从设备 t_co)
set_input_delay -clock [get_clocks clk] -max 4.000 [get_ports miso]


