SPI 接口协议的Verilog HDL 实现

1.串行外设接口SPI(Serial Peripheral Interface)是一种由Motorola 公司推出的一种同步串行接口,得到了广泛应用。SPI 接口可以共享,便于组成带多个SPI 接口器件的系统,且传送速率可编程,连接线少,具有良好的扩展性,是一种优秀的同步时序电路。

SPI,顾名思义就是串行外围设备接口,只需4 条线就可以完成主、从与各种外围器件全双工同步通讯。4 根接口线分别是:串行时钟线(SCK)、主机输入/从机输出数据线(MISO)、主机输出/从机输入数据线(MOSI)、低电平有效从机选择线CS。

2.SPI 接口的总线时序

SPI 的工作模式分为主模式和从模式,二者都需要在SCK 的作用下才能工作;但主模式不需要CS 信号,而从模式必须在CS 信号有效的情况下才能完成。不论是在主模式下还是在从模式下,都要在时钟极性(CPOL)和时钟相位(CPHA)的配合下才能有效地完成一次数据传输。其中,时钟极性表示时钟信号在空闲时的电平;时钟相位决定数据是在SCK的上升沿采样还是下降沿采样。根据时钟极性和时钟相位的不同组合,可以得到SPI 总线的4 种工作模式,如图11-45 所示。

SPI0模式下的CPOL为0,SCK的空闲电平为低;CPHA为0,数据在串行同步时钟的第一个跳变沿(由于CPOL为低,因此第1个跳变沿只能为上升沿)时数据被采样。

SPI1模式下的CPOL也为0,SCK的空闲电平为低;但是CPHA为1,数据在串行同步时钟的第二个跳变沿(由于CPOL为低,因此第2个跳变沿只能为下降沿)时数据被采样。

SPI2模式下的CPOL为1,SCK的空闲电平为高;CPHA为0,数据在串行同步时钟的第1个跳变沿(由于CPOL为高,因此第1个跳变沿只能为下降沿)时数据被采样。

SPI3模式下的CPOL为1,SCK的空闲电平为高;CPHA为1,数据在串行同步时钟的第2个跳变沿(由于CPOL为高,因此第1个跳变沿只能为上升沿)时数据被采样。

在上述4 种模式中,使用的最为广泛的是SPI0 和SPI3 方式。由于每一种模式都与其他三种不兼容,因此为了完成主、从设备间的通讯,主、从设备的CPOL 和CPHA 必须有相同的设置。读者需要注意的是:如果主设备/从设备在SCK 上升沿发送数据,则从设备/主设备最好在下降沿采样数据;如果主设备/从设备在SCK 下降沿发送数据,则从设备/主设备最好在SCK 上升沿采样数据。

在通过 HDL 语言实现SPI 接口协议完成通信或者对具有SPI 接口的芯片进行编程以及功能配置时,需要注意以下几个问题:

(1)确认接口芯片读入或送出数据发生在时钟信号的上升沿或是下降沿,并在数据保持稳定后再进行数据的读写操作;

(2)数据需保持的最短有效时间(一般而言查阅接口芯片的数据手册就可以得到),避免在接口芯片未完成读写数据时即进行下一次的操作;

(3)对于从节点主动寻求主动节点服务的接口芯片,应注意SPI 接口芯片发出中断数据请示信号后,所需的响应时间,以避免出现接口芯片发出请示服务信号后长时间处于等待状态而致使数据信息丢失等现象的出现。

(4)在进行数据通信时,确认通信字节位传输的顺序是以MSB→ LSB 方式进行,还是以LSB → MSB 的方式进行。

例子:使用Verilog HDL语言实现SPI0模式的SPI主模式,其中读、写操作都是低字节在前,高字节在后,每次传送1个字节。

module spi_master(
addr,in,out,rd,wr,cs,clk,miso,mosi,sclk
    );
 input [1:0]addr;
 input [7:0]in;
 output [7:0]out;
 input rd,wr,cs,clk;
 inout miso,mosi,sclk;
 reg [7:0]out;
 reg sclk_buffer = 0;
 reg mosi_buffer = 0;
 reg busy = 0;
 reg [7:0] in_buffer = 0;
 reg [7:0] out_buffer = 0;
 reg [7:0] clkcount = 0;
 reg [7:0] clkdiv = 0;
 reg [4:0] count = 0;
 always @(cs or rd or addr or out_buffer or clkdiv or busy)
 begin//read
out=8'bx;
if(cs&&rd)
begin
case(addr)
2'b00:out=out_buffer;
2'b01:out={7'b0,busy};
2'b10:out=clkdiv;
endcase
end
 end
 always @ (posedge clk)
 begin
if(!busy)
begin
if(cs&&wr)
begin
case(addr)
2'b00:
begin
in_buffer=in;
busy=1;
end
2'b10:
begin
clkdiv=in;
end
endcase
end
end
else
begin
clkcount=clkcount+1;
if(clkcount>=clkdiv)
begin
clkcount=0;
if((count%2)==0)
begin
mosi_buffer=in_buffer[7];
in_buffer=in_buffer<<1;
end
if(count>0&&count<17)
begin
sclk_buffer=~sclk_buffer;
end
count=count+1;
if(count>17)
begin
count=0;
busy=0;
end
end
end
 end
 always@(posedge sclk_buffer) 
 begin
 out_buffer = out_buffer << 1;
 out_buffer[0] = miso;
 end
 assign sclk = sclk_buffer;
 assign mosi = mosi_buffer;
Endmodule

原文发布于微信公众号 - 瓜大三哥(xiguazai_tortoise)

原文发表时间:2016-06-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏牛客网

Java面经:去哪儿四轮面试真题分享

废话不多说,前几天参加去哪网面试,面经如下: 去哪网java实习生面总共分为四轮(我也不知道为什么这么多)。 一面(技术面) 1.自我介绍,并分析简历上的项目,...

38160
来自专栏北京马哥教育

Python新手应该如何练手?知乎5600赞答案告诉你!

作者:小小搬运工 链接:https://www.zhihu.com/question/29372574/answer/88624507 一直在学习python,...

40270
来自专栏Jimoer

Java设计模式学习记录-责任链模式

 已经把五个创建型设计模式和七个结构型设计模式介绍完了,从这篇开始要介绍行为型设计模式了,第一个要介绍的行为型设计模式就是责任链模式(又称职责链模式)。

13820
来自专栏java一日一条

有经验的Java开发者和架构师容易犯的10个错误(上)

首先允许我们问一个严肃的问题?为什么Java初学者能够方便的从网上找到相对应的开发建议呢?每当我去网上搜索想要的建议的时候,我总是能发现一 大堆是关于基本入门的...

8320
来自专栏数据小魔方

流量结构分布图——桑基图(Sankey)

桑基图作为相对复杂的图表种类,平时很少用到,不仅仅是因为它的引用场景相对狭窄,另一方面则是制作难度相对较大,门槛较高。 不过针对第一个问题,如果你能很好地理解自...

1.3K50
来自专栏逆向技术

计算机基础知识_硬件知识

  硬件知识 计算机之父(冯·诺依曼)提出了一种结构 电子管-晶体管-集成电路-大规模集成电路 主要的要点是: 1.)计算机存储是按照二进制存储的 作用是 可...

19700
来自专栏CSDN技术头条

解析大型.NET ERP系统 20条数据库设计规范

数据库设计规范是个技术含量相对低的话题,只需要对标准和规范的坚持即可做到。当系统越来越庞大,严格控制数据库的设计人员,并且有一份规范书供执行参考。在程序框架中,...

30370
来自专栏余林丰

命令模式

当学了这个命令模式后,又一次体会到编程的艺术,明明一个看似很简单的事,却要用“复杂”的方法来实现,就像在之前我多次说到的,其实并不是“复杂”,并不是“难”,而是...

18190
来自专栏Python数据科学

Python爬虫之一个海贼迷的呐喊

海贼王已经10年了,一路陪伴了我们的点点滴滴。它热血,激情,感人,欢乐,吸引了无数男女老少的紧紧跟随。

12730
来自专栏Java学习网

最佳编码实践:搞砸代码的10种方法

 这是一篇提供有效、实用编程方法的程序箴言,作者Susan Harkins是世界最大的技术期刊出版社的主编,具有多年的实践经验;在这篇文章里她重申“最佳编码实践...

27940

扫码关注云+社区

领取腾讯云代金券