基于FPGA的QSPI底层驱动代码实现
温馨提示:这篇文章已超过382天没有更新,请注意相关的内容是否还可用!
基于FPGA的QSPI底层驱动代码实现
- QSPI简介
- 写时序
- 读时序
- QSPI实现的Verilog代码
- 仿真波形图
- 总结
QSPI简介
相信各位优秀的工程师们对SPI协议已经是非常了解了,SPI全名为串行外围设备接口(Serial Peripheral Interface),是一种高速全双工的同步通信总线,广泛应用于设备间的通讯传输。
而本文所要讲的QSPI,为SPI接口的扩展,Q代表quad即4倍传输的意思,也称为四线制SPI,因此该接口的传输速率将远远快于标准的SPI,其广泛应用于SPI Flash存储介质。下面本文将通过一个Flash芯片的Datasheet,来详细的描述该如何利用FPGA实现QSPI的通信。
写时序
由时序图可以看到,图中总共有6个信号,从上至下分别为CE(片选信号)、CLK(时钟信号)、SIO0–SIO34根数据线。其中与SPI接口相似的是片选和时钟信号不变,在读写数据时片选信号均为低电平,在采样或发送数据时均在时钟的上升沿或者下降沿。唯一的区别在数据线由原来的MOSI、MISO变成了4根数据线,那么我们该如何将这四根数据线应用起来呢?由图中可知,SIO0会发送命令、地址以及数据,而SIO1–SIO3则只发送命令和数据,再进一步观察可以看到,写命令为0x38,它由8个CLK发送完成,地址信号总共24bit,由4跟数据线在6个CLK内同时完成发送,且每根数据线所发送的起始比特位都不同,最后便是发送数据,同理也由4根数据线同时进行发送,1个CLK发送4bit数据,发送的大小可由用户自己设定。总结一下,QSPI通信写的流程可以概括为先发送一个字节的命令字(这个命令字对于不同的芯片是不一样的),再是发送3个字节的地址(同理),最后才是发送数据。因此在FPGA的设计上就有思路了,最简单的方法就是采用状态机来描述这一过程,具体代码将在下面展示。
读时序
由图可知,读时序的操作流程与写时序大同小异,只是命令字由0x38变成了0xEB,其余操作流程均与写时序相同,因此不再进行详细阐述。
但需要注意的是,由SPI扩展为QSPI,它已经不是全双工通信了,而是变成了半双工。SIO0–SIO3 4根线将变成三态门,也就是FPGA中的inout接口,需要满足特定的条件才能输入或者输出数据。
下面将给出QSPI通信的底层驱动代码,在实际工程应用中,还需要结合芯片的数据手册来编写应用层的程序,再结合底层的逻辑来实现特定的功能,例如利用QSPI或者SPI接口对某个Flash芯片进行读写。
QSPI实现的Verilog代码
module QSPI_DRIVE #( parameter DIV = 3 )( input wire clk, input wire rst, //--------应用层传输进该模块的命令、地址、数据等--------// input wire [3:0] i_cmd_mode, input wire [7:0] i_flash_cmd, input wire [23:0] i_addr, input wire [7:0] i_data, input wire [15:0] i_data_num, input wire i_wr, output reg [7:0] o_data, //---------QSPI 接口---------// output reg qspi_cs, output reg qspi_csk, inout reg qspi_sio0, inout reg qspi_sio1, inout reg qspi_sio2, inout reg qspi_sio3 ); reg [7:0] div_cnt; reg [7:0] cmd_cnt; reg [7:0] addr_cnt; reg [7:0] data_cnt; reg [15:0] num_cnt; reg [3:0] cmd_mode_lock; reg [7:0] flash_cmd_lock; reg [23:0] addr_lock; reg [7:0] r_data_temp; reg qspi_sckd0; wire qspi_sck_p,qspi_sck_n; //---------------FSM---------------// reg [7:0] state,n_state; localparam IDLE = 8'h00, START = 8'h01, CMD = 8'h02, ADDR = 8'h04, DATA = 8'h08, STOP = 8'h10; always@(posedge clk)begin if(rst) state


