一. SPI总线协议 SPI(Serial Peripheral Interface)接口,中文为串行外设接口。它只需要3根线或4根线即可完成通信工作(这里讨论4根线的情况)。
这4根通信线分别为NCS/NSS(片选信号)、SCK/SCLK(串行同步时钟)、MOSI/SDO(主机输出从机输入,Master Output Slave Input)、MISO/SDI(主机输入从机输出)。
SPI通信有四种方式,由CPOL(时钟极性)、CPHA(时钟相位)的4种组合决定的。CPOL决定总线空闲时,SCK是高电平还是低电平(CPOL=,0,无数据传输时,SCK=0;CPOL=1,无数据传输时,SCK=1)。CPHA决定在数据开始传输时,SCK第几个跳变沿采集数据(CPHA=0,开始传输时,在第一个跳变沿采集数据,第二个跳变沿改变发送数据(即改变MISO或者MOSI线上电平);CPHA=1,开始传输是,在第一个跳变沿改变发送的数据,在第二个跳变沿采集数据)(见图1)。

图1
确立可靠通信前,必须保证主从机处于同一种的传输方式,这里为方便起见,专门以CPOL=0,CPHA=0的传输方式进行讨论。需要注意的是:在CPOL=0,CPHA=0的情况下,主从机都在SCK上跳沿对数据进行采集,SCK下跳沿改变总线电平(见图2)。

图2
这里在使用FPGA实现SPI模块时,做一个规定:
1. 使用CPOL=0,、CPHA=0的传输方式;
2. 传输时,以最高位先输出,最后输出最低位;
3. FPGA实现的SPI模块作从机,SCK由外部主机提供;
4. 通信数据长度为8位。
二. FPGA的SPI从机实现 实现SPI从机,可以分为两个模块:一个是SPI接收模块,另一个则是SPI发送模块。
1. 首先确定模块的输出输入管脚 由标题一可以知道,SPI通信脚有4根线,我们还是用到时钟总线和模块复位脚,因此模块管脚可以定义为 module myspi(nrst, clk, ncs, mosi, miso, sck);input clk, nrst;input ncs, mosi, sck;output miso;
2. SCK跳变沿检测 原理十分简单:使用寄存器记录SCK状态,由状态判断SCK是否出现跳变沿。
reg[2:0] sck_edge; always @ (posedge clk or negedge nrst) begin if(~nrst) begin sck_edge <= 3'b000; end else begin sck_edge <= {sck_edge[1:0], sck}; end endwire sck_riseedge, sck_falledge; assign sck_riseedge = (sck_edge[2:1] == 2'b01); //检测到SCK由0变成1,则认为发现上跳沿 assign sck_falledge = (sck_edge[2:1] == 2'b10); //检测到SCK由1变成0,则认为发现下跳沿 |