概述
SPI = Serial Peripheral Interface,是串行外围设备接口,是一种高速,全双工,同步的通信总线。
优点
支持全双工
支持高速
协议支持字长不限于8bit,可以根据应用灵活选择消息字长。
硬件连接简单
缺点
相比I2C多两条线
没有寻址机制,只能靠片选选择不同的设备
没有回应ACK机制,主设备不知道消息发送是否成功
典型应用仅支持单主控
硬件结构
信号定义
SCK
:Serial Clock,时钟信号,由主设备产生。
MOSI
:Master Output,Slave Input 主发从收信号。在片选信号有效时,数据由高位到低位,在时钟的上升沿依次发送给从设备。
MISO
:Master Input,Slave Output 主收从发信号,在片选信号有效时,数据由高位到低位,在时钟的上升沿依次发送给主设备。
SS/CS
:Slave Select 片选信号,低有效,由主设备控制。即只有片选信号为预先规定的使能信号时,对应的芯片操作才有效,这使得在同一总线上连接多个SPI设备成为可能。
电路连接
单个主设备和单个从设备:
单个主设备和多个从设备,通过用多个片选信号或者菊花链的形式完成。
传输模式
通过设置相关控制寄存器,SPI可以有四种传输模式。
1、时钟空闲时的电平为高或低。
2、数据采样发生在时钟(SCK)的上/下边沿。
将以上两种情况两两组合,即可得四种传输模式。
数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取,完成一位数据传输,输入与输出原理相近。这样通过至少8次时钟信号的改变(上升沿和下降沿为一次),就可以完成8位数据的传输。如下图所示。
标准SPI读
片选→读指令→地址→数据读出
标准SPI写
片选→写指令→地址→数据写入
Verilog代码解析
本文以SPI Master控制器为例来对Verilog源码进行分析,参考资料为《VERILOG HDL应用程序设计实例精讲》。
1、时钟分频模块,将原始时钟进行四分频,过程较为简单,不再详述。
module clkdiv(clk,clkout); input clk; output clkout; reg [1:0]cnt=2'd0; reg clkout=1'b0; always @(posedge clk)begin if(cnt==2'd1)begin clkout<=1'b1; cnt<=cnt+2'd1; end else if(cnt == 2'd3)begin clkout<=1'b0; cnt<=2'd0; end else begin cnt<=cnt+2'd1; end end endmodule
2、SPI发送数据部分,在spiclk的上升沿完成数据的传输。spics为片选信号,低有效;spido为输出的数据;dstate为FSM变量。dsend为待传送数据,其中部分数据过程重复,代码中仅保留首尾数据的传输过程。
begin case (dstate) 8'd0: begin spics <= 1'b0; spiclk <= 1'b1; spido <= 1'b1; dstate <= 8'd1; end 8'd1: begin spics <= 1'b0; spiclk <= 1'b1; spido <= 1'b1; dstate <= 8'd2; end 8'd2: begin spics <= 1'b0; spiclk <= 1'b0; spido <= 1'b1; dstate <= 8'd3; end 8'd3: begin spics <= 1'b0; spiclk <= 1'b1; spido <= dsend[7]; dstate <= 8'd4; end 8'd4: begin spics <= 1'b0; spiclk <= 1'b0; spido <= dsend[7]; dstate <= 8'd5; end …… 8'd17: begin spics <= 1'b0; spiclk <= 1'b1; spido <= dsend[0]; dstate <= 8'd18; end 8'd18: begin spics <= 1'b0; spiclk <= 1'b0; spido <= dsend[0]; dstate <= 8'd19; end 8'd19: begin spics <= 1'b0; spiclk <= 1'b1; spido <= 1'b1; dstate <= 8'd20; end 8'd20: begin spics <= 1'b0; spiclk <= 1'b1; spido <= 1'b1; dstate <= 8'd0; spistate <= idle; end endcase end default: begin spics <= 1'b1; spiclk <= 1'b1; spido <= 1'b1; spistate <= 2'b00; end endcase end
可以看到当片选信号spics为低有效时,数据在spiclk的上升沿按顺序被发送至SPI总线上,数据信号spido与输入数据相对应,SPI Master发送时序得到验证。
3、SPI接收数据部分,参数定义与2一样,其中部分数据过程重复,代码中仅保留首尾数据的传输过程。在时钟的下降沿进行数据的接收。
begin case (dstate) 8'd0: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd1; end 8'd1: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd2; end 8'd2: begin spics <= 1'b0; spiclk <= 1'b0; dstate <= 8'd3; end 8'd3: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd4; end 8'd4: begin spics <= 1'b0; spiclk <= 1'b0; dreceive[7] <= spidi; dstate <= 8'd5; end 8'd5: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd6; end …… 8'd18: begin spics <= 1'b0; spiclk <= 1'b0; dreceive[0] <= spidi; dstate <= 8'd19; end 8'd19: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd20; dataout <= dreceive; end 8'd20: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd0; spistate <= 2'b00; end endcase end
由上图分析看出,收到的数据与SPI传输的数据相对应,SPI接收数据部分得到正确验证。
实验项目框图:
实验心得:
1、在给复位信号低电平时时间过短,分频后时钟上升沿还未到复位信号就拉高了,导致未进行有效复位。
2、进行发送/接收状态检测时设置的计数子过大,如下图,每过40个时钟周期进行一次检测,当仿真时间过短时,容易看不到结果。
if(cnt == 8'd40) begin cnt <= 8'd0; if((wr == 1'b0) && (rd == 1'b1)) begin spistate <= send_data; dstate <= 8'd0; dsend <= datain; end else if((wr == 1'b1) && (rd == 1'b0)) begin spistate <= receive_data; dstate <= 8'd0; end end else begin cnt <= cnt + 8'd1; end
3、若结果出现问题,将相关控制信号添加至窗口,观察其状态,分析程序存在的问题。
-
Verilog
+关注
关注
28文章
1360浏览量
111118 -
SPI
+关注
关注
17文章
1737浏览量
93395 -
通信总线
+关注
关注
0文章
45浏览量
9947
原文标题:SPI详解及Verilog源码分析
文章出处:【微信号:gh_9d70b445f494,微信公众号:FPGA设计论坛】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
SPI总线的原理与Verilog设计实现

SPI总线概述
怎么使用FPGA实现SPI总线的通信接口?
STM32通信接口之硬件SPI概述
介绍一下SPI通信总线构成与通信特点
用SPI总线实现DSP和MCU之间的高速通信
使用Verilog实现SPI串行总线接口的资料和源代码免费下载

评论