1. 项目概述
在FPGA开发中,QSPI PSRAM因其高速、低功耗和低成本的特点,成为嵌入式系统中常用的外部存储器解决方案。APS6404L-3SQR是一款64Mb容量的QSPI PSRAM芯片,支持最高104MHz的时钟频率。本文将详细介绍基于FPGA的APS6404L-3SQR QSPI PSRAM驱动设计中的顶层框架实现,重点解析命令控制机制和状态机设计。
2. 驱动设计整体架构
2.1 硬件接口设计
APS6404L-3SQR采用标准的QSPI接口,包含以下信号线:
- QSPI_CLK:时钟信号
- QSPI_CS:片选信号
- QSPI_SIO0~SIO3:四线数据总线
在FPGA端,我们需要特别注意以下几点:
- 四线数据总线需要配置为双向IO
- 时钟频率需要根据FPGA和PSRAM的时序要求合理设置
- 片选信号需要与时钟严格同步
2.2 状态机设计原理
驱动核心采用有限状态机(FSM)控制操作流程,主要状态包括:
- 上电初始化(POWER_UP)
- 复位使能(RSTEN)
- 执行复位(RST)
- 读取ID(READ_ID)
- 进入QPI模式(MODE_QPI)
- 写入数据(WRITE)
- 读取数据(READ)
- 退出QPI模式(MODE_QPI_EXIT)
状态转换基于两个关键信号:
- w_spi_data_ready:SPI操作完成标志
- w_qspi_data_ready:QSPI操作完成标志
3. 关键模块实现细节
3.1 命令控制模块
命令控制是驱动的核心,需要处理多种操作命令:
verilog复制localparam
PSRAM_READ = 8'h03,
PSRAM_FAST_READ = 8'h0B,
PSRAM_FAST_READ_QUAD = 8'hEB,
PSRAM_WRITE = 8'h02,
PSRAM_QUAD_WRITE = 8'h38,
PSRAM_ENTER_QUAD_MODE = 8'h35,
PSRAM_EXIT_QUAD_MODE = 8'hF5,
PSRAM_RESET_ENABLE = 8'h66,
PSRAM_RESET = 8'h99;
命令发送逻辑采用状态机控制,每个状态对应特定的命令序列:
verilog复制always @(posedge clk_i, negedge rstn_i)
begin
if (!rstn_i) begin
r_spi_driver_valin <= 1'b0;
r_spi_driver_cmdin <= 'd0;
end else if ((r_fsm_current == FSM_RSTEN) && w_spi_ready && (r_fsm_cnt == 'd0)) begin
r_spi_driver_valin <= 1'b1;
r_spi_driver_cmdin <= PSRAM_RESET_ENABLE;
end
// 其他命令发送逻辑...
end
3.2 数据通路设计
数据通路需要考虑以下几点:
- SPI和QSPI模式切换
- 数据方向控制
- 时钟域同步
双向IO控制逻辑示例:
verilog复制assign QSPI_SI_SIO0 = (spi_cmd_flag | spi_addr_flag) ? w_spi_miso :
((qspi_cmd_flag | qspi_addr_flag | qspi_wrdata_flag) ? w_qspi_so0 : 1'bz);
assign QSPI_SO_SIO1 = (qspi_cmd_flag | qspi_addr_flag | qspi_wrdata_flag) ? w_qspi_so1 : 1'bz;
// 其他数据线类似...
3.3 时序控制
严格的时序控制是确保通信可靠的关键:
- 上电后需要等待至少200μs(VDD稳定)
- 命令之间需要适当的延时
- 数据读写需要满足建立/保持时间要求
时序控制代码片段:
verilog复制// 上电延时计数
always @(posedge clk_i, negedge rstn_i)
begin
if (!rstn_i)
r_power_up_cnt <= 'd0;
else if (r_power_up_cnt >= 'd20_000)
r_power_up_cnt <= r_power_up_cnt;
else
r_power_up_cnt <= r_power_up_cnt + 'd1;
end
4. 实际应用与优化
4.1 性能优化技巧
- 突发传输优化:合理设置突发长度可以减少命令开销
- 时钟优化:根据系统需求选择最高支持时钟频率
- 流水线设计:重叠命令发送和数据传输提高吞吐量
4.2 常见问题排查
-
初始化失败:
- 检查电源稳定性
- 验证复位序列是否正确
- 确认时钟频率是否在规格范围内
-
数据读写错误:
- 检查时序约束是否满足
- 验证数据线方向控制逻辑
- 确认地址对齐是否正确
-
状态机卡死:
- 添加超时机制
- 增加状态机错误恢复路径
- 添加调试输出监控状态转换
5. 测试与验证
5.1 测试平台搭建
建议测试平台包含以下组件:
- FPGA开发板
- 逻辑分析仪(抓取QSPI信号)
- 示波器(检查电源质量)
- 测试模式生成器
5.2 测试用例设计
基本测试场景应包括:
- 单字节读写测试
- 突发读写测试
- 边界地址测试
- 长时间稳定性测试
测试数据生成示例:
verilog复制always @(posedge w_clk_80m, negedge rst_n) begin
if (!rst_n) begin
PsRamCtrWrDat <= 'd0;
PsRamCtrWr <= 'd0;
end else if (cnt_4freq == 2'b11) begin
PsRamCtrWrDat <= {cnt,cnt_1d,cnt_2d,cnt_3d};
PsRamCtrWr <= 1'b1;
end else begin
PsRamCtrWrDat <= 'd0;
PsRamCtrWr <= 'd0;
end
end
6. 工程实践建议
- 版本控制:建议使用Git管理代码,特别是状态机设计和时序参数
- 参数化设计:将关键时序参数设为宏定义,便于移植和调整
- 文档记录:详细记录每个状态的功能和转换条件
- 仿真验证:在综合前进行充分的仿真测试
在实际项目中,我发现以下几点特别重要:
- 状态机的设计要尽可能简单明了
- 关键信号要添加调试标记(如PAP_MARK_DEBUG)
- 时序约束要严格匹配PSRAM的规格要求
- 预留足够的测试点便于问题排查
通过本文介绍的设计方法,可以实现稳定可靠的QSPI PSRAM驱动,满足大多数嵌入式系统的存储需求。根据具体应用场景,还可以进一步优化性能或增加功能,如DMA支持、错误检测等。