SPI总线的verilog实现

发布者:tnzph488最新更新时间:2016-03-08 来源: eefocus关键字:SPI总线  verilog 手机看文章 扫描二维码
随时随地手机看文章
SPI一共4个线:

*)SCK 串行时钟线:时钟信号

*)MISO 主机输入/从机输出线;

*)MOSI 主机输出/从机输入线;

*)CS 片选那个从机进行通信。

无应答机制

 

一定要搞清楚从设备是上升沿还是下降沿接受数据。

 

时钟极性:一根线上比如:主的SDO和从的SDI时钟极性相反,也就是如果主SDO是上升沿有效,那么从SDI下降沿有效。

 

时钟相位为0:第一个跳变沿数据采样,所以时钟前采样,时钟后输出;

时钟相位为1:第二个跳变沿数据采样,所以时钟前输出,时钟后采样。

一般使用0模式。

 

管脚SS非为判断主从的标志,SS非为低为从,高为主。

 

IP可划分为:硬IP,软IP,和两者之间的固IP

 

SPI

 

module spi_mosi(rst,clk,rd,wr,datain,spics,spiclk,spido,spidi,dataout);

input rst;//置位信号,低有效

input clk;//时钟信号

input rd;//接受数据命令

input wr;//发送数据命令

input spidi;//SPI数据输入信号

input [7:0] datain;//待发送数据~输入

 

output spics;//SPI片选信号

ouput spiclk;//SPI时钟信号

output spido;//SPI数据输出信号

output [7:0] dataout;//待接受数据~输出

 

reg spics;

reg spiclk;

reg spido;

reg [7:0] dstate,dsend,dataout,dreceive;

reg [1:0] spistate;

 

parameter idle = 2'b00;

parameter send_data=2'b01;

parameter receive_data=2'b10;

 

initial

begin

  spics<=1'b1;

  spiclk<=1'b1;

  spido<=1'b1;

end

 

always @(posedge clk)

  begin

    if(!rst)

       begin

          spistate<=idle;

          spics<=1'b1;

          spiclk<=1'b1;

          spido<=1'b1;

          dstate<=8'd0;

        end

    else

        begin

           case(spistate)

              2'b00:

               begin

                 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

                  else

                       begin

                          spistate<=idle;

                          dstate<=8'd0;

                        end

                 end

              2'b01://发送数据状态

                begin

                  case(state)

                  8'd0://产生片选信号有效

                    begin

                      spics<=1'b0;

                      spiclk<=1'b1;

                      spicdo<=1'b1;

                      dstate<=8'd1;

                   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'd5:

                       begin

                           spics<=1'b0;

                           spiclk<=1'b1;

                           spido<=dsend[6];

                           dstate<=8'd6;

                       end

                     8'd6:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b0;

                            spido<=dsend[6];

                            dstate<=8'd7;

                        end

                     8'd7:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b1;

                            spido<=dsend[5];

                            dstate<=8'd8;

                        end

                     8'd8:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b1;

                            spido<=dsend[5];

                            dstate<=8'd9;

                        end

                     8'd9:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b1;

                            spido<=dsend[4];

                            dstate<=8'd10;

                        end

                     8'd10:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b0;

                            spido<=dsend[4];

                            dstate<=8'd11;

                        end

                     8'd11:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b1;

                            spido<=dsend[3];

                            dstate<=8'd12;

                        end

                     8'd12:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b1;

                            spido<=dsend[3];

                            dstate<=8'd13;

                        end

                     8'd13:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b0;

                            spido<=dsend[2];

                            dstate<=8'd14;

                        end

                     8'd14:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b1;

                            spido<=dsend[2];

                            dstate<=8'd15;

                        end

                     8'd15:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b0;

                            spido<=dsend[1];

                            dstate<=8'd7;

                        end

                     8'd16:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b1;

                            spido<=dsend[1];

                            dstate<=8'd17;

                        end

                     8'd17:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b0;

                            spido<=dsend[0];

                            dstate<=8'd18;

                        end

                     8'd18:

                        begin

                            spics<=1'b0;

                            spiclk<=1'b1;

                            spido<=dsend[0];

                            dstate<=8'd19;

                        end

                     8'd19:

                        begin

                            spics<=1'b1;

                            spiclk<=1'b1;

                            spido<=1'b1;

                            dstate<=8'd20;

                        end

                     8'd20:

                        begin

                            spics<=1'b1;

                            spiclk<=1'b1;

                            spido<=1'b1

                            dstate<=8'd0;

                            spistate<=idle;

                        end

                     default

                         begin

                             spics<=1'b1;

                             spiclk<=1'b1;

                             spido<=1'b1;

                             spistate<=idle;

                          end

                  endcase

                end

           2'b10://接受数据状态

              begin

                 case(dstate)//片选信号有效

                        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;            
    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'd6:
   begin
    spics <= 1'b0;
    spiclk <= 1'b0;
    dreceive[6] <= spidi;
    dstate <= 8'd7;
   end
   8'd7:
   begin
    spics <= 1'b0;
    spiclk <= 1'b1;            
    dstate <= 8'd8;
   end
   8'd8:
   begin
    spics <= 1'b0;
    spiclk <= 1'b0;
    dreceive[5] <= spidi;
    dstate <= 8'd9;
   end
   8'd9:
   begin
    spics <= 1'b0;
    spiclk <= 1'b1;            
    dstate <= 8'd10;
   end
   8'd10:
   begin
    spics <= 1'b0;
    spiclk <= 1'b0;
    dreceive[4] <= spidi;
    dstate <= 8'd11;
   end
   8'd11:
   begin
    spics <= 1'b0;
    spiclk <= 1'b1;            
    dstate <= 8'd12;
   end
   8'd12:
   begin
    spics <= 1'b0;
    spiclk <= 1'b0;
    dreceive[3] <= spidi;
    dstate <= 8'd13;
   end
   8'd13:
   begin
    spics <= 1'b0;
    spiclk <= 1'b1;
    dstate <= 8'd14;
   end
   8'd14:
   begin
    spics <= 1'b0;
    spiclk <= 1'b0;
    dreceive[2] <= spidi;
    dstate <= 8'd15;
   end
   8'd15:
   begin
    spics <= 1'b0;
    spiclk <= 1'b1;            
    dstate <= 8'd16;
   end
   8'd16:
   begin
    spics <= 1'b0;
    spiclk <= 1'b0;
    dreceive[1] <= spidi;
    dstate <= 8'd17;
   end
   8'd17:
   begin
    spics <= 1'b0;
    spiclk <= 1'b1;            
    dstate <= 8'd18;
   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;
    spido  <= 1'b1;
    dstate <= 8'd20;
    dataout<= dreceive;
   end
   8'd20:
   begin
    spics <= 1'b1;       //片选信号无效
    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 <= idle;
     end
endcase //对应上面的发送数据情形
end     //对应上面的RST没有按下的情形
end        //对应最上面的always@(posedge clk)
endmodule

关键字:SPI总线  verilog 引用地址:SPI总线的verilog实现

上一篇:I2S音频总线学习(一)数字音频技术
下一篇:1553B总线常见问题

推荐阅读最新更新时间:2024-05-03 00:14

关于I2C和SPI总线协议
I2Cvs SPI 现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral Interface)的身影。原因是这两种通信协议非常适合近距离低速芯片间通信。Philips(for IIC)和Motorola(for SPI) 出于不同背景和市场需求制定了这两种标准通信协议。 IIC 开发于1982年,当时是为了给电视机内的CPU和外围芯片提供更简易的互联方式。电视机是最早的嵌入式系统之一,而最初的嵌入系统是使用内存映射(memory-mapped I/O)的方式来互联微控制器和外围设备的。要实现内存映射,设备必须并联入微
[嵌入式]
两自由度振动偏移量实时采集设备的设计与实现
  光电鼠标的工作机理是采用一种基于CMOS成像的图像识别方法,通过一个感光眼,不断的对物体进行拍照,并将前后两次图像进行DSP处理,得到移动的方向和间隔,因此,光电鼠标芯片具有一种传感器的基本功能。振动的检测,其基本原理可以归结到一种位移的检测。只是此种位移是围绕某个基本点进行往复移动。因此设计了一种采用光电鼠标传感器原理进行振动检测的设备。   该设备是完全从市场应用的角度进行设计的,设备等间隔连续采集到的△x和△y值经上位机应用程序可以绘制出设备的各种运动参数曲线(包括位移、速度和加速度曲线)并进行相应的运动学分析。   采用现行的鼠标芯片,采集设备可以在速度≤1m/s,加速度≤160m/s2 范围内实现偏移量在精度
[嵌入式]
基于Verilog的DDS波形发生器的分析与实现(三角波、正弦波)
最近学习了一下关于DDS的相关知识,本篇概要记录一下自己的理解与实现。 DDS信号发生器采用直接数字频率合成(Direct Digital Synthesis,简称DDS)技术,把信号发生器的频率稳定度、准确度提高到与基准频率相同的水平,并且可以在很宽的频率范围内进行精细的频率调节。采用这种方法设计的信号源可工作于调制状态,可对输出电平进行调节,也可输出各种波形。 下图为DDS 的基本结构图 由上图 可以看出,DDS 主要由相位累加器、相位调制器、波形数据表以及 D/A 转换器构成。 相位累加部分控制输出波形频率,相位字输入部分来改变相位,ROM表中存储一个周期波形的幅度值。 其中相位累加器由 N 位加法器与 N 位寄
[测试测量]
基于<font color='red'>Verilog</font>的DDS波形发生器的分析与实现(三角波、正弦波)
基于SATAII协议的CRC32并行算法的研究
    随着通信和存储技术的发展,数据传输速率在急剧提高。然而由于通道传输特性不理想及可能受到干扰或噪声的影响,数据传输过程中难免会发生错误。如何保证可靠性是正确设计一个通信系统或数据存储系统的关键问题所在。     信道编码是提高可靠性的必要手段,实现检错功能的差错控制方法很多,包括奇偶校验、重复码校验、校验和检测、行列冗余码校验、恒比码校验、CRC校验等。其中CRC循环冗余校验是一种高效率的差错控制方案,其特点是编码和解码的方法简单、检错纠错能力强,因而应用于许多领域尤其是串行通信中以实现差错控制。     CRC循环校验算法占用的系统资源少,其实现方法分为软件实现和硬件实现。文中在研究CRC32算法的基础上,结合SATAⅡ协
[嵌入式]
基于Verilog HDL语言的CAN总线控制器设计及验证
0 引言     CAN(Controller Area Network)是由ISO定义的一种串行通信总线,它是一种能有效地支持高安全等级的分布实时控制的新一代网络通信协议,属于现场总线范畴。CAN最早被设计作为汽车环境中微控制器的通讯,在车载各电子控制装置与ECU之间交换信息,形成汽车电子控制网络,目前应用领域已经相当广泛。     近年来,支持CAN协议的芯片不断推出,给CAN总线用户带来了极大的方便。随着我国对现场总线技术需求的增加,CAN总线已经会成为我国最常用的现场总线之一。     基于CAN总线的ECU电子控制单元的开发,也是现在最热门的研究。现在对CAN总线芯片的研究已经不再局限于单一芯片的研究,而是把所有的功能芯
[嵌入式]
基于Verilog计算精度可调的整数除法器的设计
  除法器是电子技术领域的基础模块,在电子电路设计中得到广泛应用。目前,实现除法器的方法有硬件实现和软件实现两种方法。硬件实现的方法主要是以硬件的消耗为代价,从而有实现速度快的特点。用硬件的方法来实现除法器的研究很多,如利用微处理器实现快速乘除法运算,FPGA实现二进制除法运算,模拟除法器等;而通过软件实现的除法器算法,可以大大提高器件的工作频率和设计的灵活性,可以从总体上提高设计性能,而设计高效实用的算法是除法器的关键,故除法器的算法研究成为现今热点。      目前,软件方面主要是通过减法算法来实现除法运算,把被除数作为被减数,除数作为减数,作减法,直到被减数小于减数为止,记录能够相减的次数即得到商的整数部分。将所得的余数乘以
[嵌入式]
基于<font color='red'>Verilog</font>计算精度可调的整数除法器的设计
SPI总线的特点、工作方式及常见错误解答
1.SPI总线简介   SPI(serial peripheral interface,串行外围设备接口)总线技术是Motorola公司推出的一种同步串行接口。它用于CPU与各种外围器件进行全双工、同步串行通讯。它只需四条线就可以完成MCU与各种外围器件的通讯,这四条线是:串行时钟线(CSK)、主机输入/从机输出数据线(MISO)、主机输出/从机输入数据线(MOSI)、低电平有效从机选择线CS。当SPI工作时,在移位寄存器中的数据逐位从输出引脚(MOSI)输出(高位在前),同时从输入引脚(MISO)接收的数据逐位移到移位寄存器(高位在前)。发送一个字节后,从另一个外围器件接收的字节数据进入移位寄存器中。即完成一个字节数据传输的
[工业控制]
SPI总线驱动(C语言源程序)
/*-------------------- 〖说明〗SPI总线驱动源程序 默认11.0592Mhz的晶振。 〖文件〗93CXX.C ﹫2003/5/12 ---------------------*/ /*通用93c06-93c86系列使用说明 93c06=93c4693c56=93c6693c76=93c86*/ //dipx 可以自行定义 #i nclude AT89X52.H #i nclude "intrins.h" /*----------------------------------------------------- SPI93cXX系列时序函数调用(普通封装) 调用方式:自行定义﹫2001/05/12 函数
[单片机]
小广播
最新嵌入式文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved