前言

当你器件的引脚贼少的时候,需要主机和从机通信,spi就派上了用场,它可以一对多,但只是片选到的从机能和主机通信,其他的挂机。

spi:serial peripheral interface 串行外围接口

大致了解:

spi是个同步协议,数据在master和slaver间交换通过时钟sck,由于它是同步协议,时钟速率就可以各种变换。

sck:主机提供,从机不能操控,从器件由主机产生的时钟控制。数据只有在sck来了的上升沿或者下降沿才传输。

高级一点的spi芯片有配置寄存器,高级一点的工作有四种模式,采样相位和sck空闲电平可配置。

当然在这里我们主要实现简单的spi协议:sck是系统时钟的四分频,wr请求信号有效时,主机开始工作,数据位8bit,sck空闲时低电平,工作时第一个沿数据传输。只有一个从机,cs低电平片选。

看下结构:

接口定义:

编码实现:(版权所有,请勿用于商业用途,仅供学习使用)

 //************************************************
 //  Filename      : spi_ms_test1.v
 //  Author        : Kingstacker
 //  Company       : School
 //  Email         : kingstacker_work@163.com
 //  Device        : Altera cyclone4 ep4ce6f17c8
 //  Description   : spi master module;data 8bit;sck is 4 div of the clk;
 //************************************************
 )(
     //input;
     input    wire    clk,
     input    wire    rst_n,
     input    wire    wr, //send request;
     :]    master_din, //the data you want send;
     input    wire    miso, //the data form slave;
     //output;
     output   reg     cs, //slave select;
     output   reg     sck, //data exchange clock;
     output   reg     mosi,    //master out;
     :]    master_dout //the data you received;
 );
 :] DIV_NUMBER = ;      //div number,you can change;
 ) - 'b1;  //max cnt number,6/2 -1 ;
 reg cnt; //sck cnt;
 reg sck_en; //enable sck;
 reg data_cnt_en;
 reg sck_reg1;
 reg sck_reg2;
 wire sck_p; //posedge sck;
 wire sck_n; //negedge sck;
 wire send_over;
 'b00;
 'b01;
 'b10;
 :] cstate;
 :] data_cnt; //cnt the send data;
 :] master_din_reg;
 :] master_dout_reg;
 :] mosi_cnt;
 //produce sck;
 always @(posedge clk or negedge rst_n) begin
     if (~rst_n) begin
         cnt <= ;
         sck <= 'b0;
     end //if
     else begin
         'b1) begin
             if (cnt == CNT_MAX) begin
                 cnt <= ;
                 sck <= ~sck;
             end
             else begin
                 cnt <= cnt + 'b1;
                 sck <= sck;
             end
         end
         else begin
             cnt <= ;
             sck <= 'b0;
         end
     end //else
 end //always
 //produce sck_p and sck_n;
 always @(posedge clk or negedge rst_n) begin
     if (~rst_n) begin
         sck_reg1 <= 'b0;
         sck_reg2 <= 'b0;
     end //if
     else begin
         sck_reg1 <= sck;
         sck_reg2 <= sck_reg1;
     end //else
 end //always
 assign sck_p = (sck_reg1 & (~sck_reg2)); //sck posedge;
 assign sck_n = ((~sck_reg1) & sck_reg2); //sck negedge;
 //fsm;hot code;
 always @(posedge clk or negedge rst_n) begin
     if (~rst_n) begin
         cstate <= IDEL;
     end
     else begin
         case (cstate)
             IDEL:    cstate <= (wr)? SEND : IDEL;
             SEND:    cstate <= (send_over) ? FINISH : SEND;
             FINISH:  cstate <= IDEL;
             default: cstate <= IDEL;
         endcase //case
     end
 end
 always @(posedge clk or negedge rst_n) begin
     if (~rst_n) begin
         cs <= 'b1;
         data_cnt_en <= 'b0;
         sck_en <= 'b0;
         master_din_reg <= ;
         master_dout <= ;
     end
     else begin
         case (cstate)
             IDEL: begin
             data_cnt_en <= 'b0;
             master_din_reg <= (wr) ? master_din : master_din_reg; //load the data you want send to slaver;
             end
             SEND: begin
                 data_cnt_en <= 'b1;
                 cs <= 'b0;
                 sck_en <= 'b1;
                 master_dout <= (send_over) ? master_dout_reg : master_dout; //master receiverd data;
             end
             FINISH: begin                  //send and load ok;
                 sck_en <= 'b0;
                 cs <= 'b1;
                 data_cnt_en <= 'b0;
             end
             default: begin
                 cs <= 'b1;
                 sck_en <= 'b0;
                 data_cnt_en <= 'b0;
             end
         endcase //case
     end
 end
 always @(posedge clk or negedge rst_n) begin
     if (~rst_n) begin
         data_cnt <= ;
     end
     else begin
         data_cnt <= (data_cnt_en) ? (data_cnt + 'b1) : 5'd0; //4 div * 8bit = 32 cnt;
     end
 end
 'b0;
 //rising edge miso;
 always @(posedge clk or negedge rst_n) begin
     if (~rst_n) begin
         master_dout_reg <= ;
     end
     else begin
         master_dout_reg <= (sck_p) ? {master_dout_reg[:],miso} : master_dout_reg;
     end
 end
 //miso;
 always @(posedge clk or negedge rst_n) begin
     if (~rst_n) begin
         mosi_cnt <= ;
     end
     else begin
         if (sck_n) begin
             'd7) begin
                 mosi_cnt <= ;
             end
             else begin
                 mosi_cnt <= mosi_cnt + 'b1;
             end
         end
         else begin
             mosi_cnt <= mosi_cnt;
         end
     end
 end
 always @(posedge clk or negedge rst_n) begin
     if (~rst_n) begin
         mosi <= 'b0;
     end
     else begin
         mosi <= (sck_n) ? master_din_reg['d7-mosi_cnt] : mosi;
     end
 end
 endmodule

仿真:

综合资源使用:

Fmax:

以上。

spi master接口的fpga实现的更多相关文章

  1. spi slaver接口的fpga实现

    前言 spi从机接口程序,数据位8bit,sck空闲时低电平,工作时第一个沿数据传输.只有一个从机,cs低电平片选,slaver开始工作. 流程: 接口定义: 编码实现:(版权所有,请勿用于商业用途, ...

  2. ARM与FPGA通过spi通信设计2.spi master的实现

    这里主要放两个代码第一个是正常的不使用状态机的SPI主机代码:第二个是状态机SPI代码 1.不使用状态机:特权同学<深入浅出玩转FPGA>中DIY数码相框部分代码: /////////// ...

  3. Linux SPI总线和设备驱动架构之二:SPI通用接口层

    通过上一篇文章的介绍,我们知道,SPI通用接口层用于把具体SPI设备的协议驱动和SPI控制器驱动联接在一起,通用接口层除了为协议驱动和控制器驱动提供一系列的标准接口API,同时还为这些接口API定义了 ...

  4. [转载]Linux驱动-SPI驱动 之二:SPI通用接口层

    通过上一篇文章的介绍,我们知道,SPI通用接口层用于把具体SPI设备的协议驱动和SPI控制器驱动联接在一起,通用接口层除了为协议驱动和控制器驱动提供一系列的标准接口API,同时还为这些接口API定义了 ...

  5. SPI通信实验---verilog(FPGA作为从机,使用可读可写)

    本实验讲究实用性,故设计思想为:主机先向从机发送地址,若是向从机写入数据,则向从机发送数据,若是读取从机数据,则向从机发送时钟,然后在时钟下降沿读取数据即可.cs信号上升沿作为SPI通信的结束信号.r ...

  6. Zynq-PL中创建AXI Master接口IP及AXI4-Lite总线主从读写时序测试(转)

    转载:原文  http://www.eefocus.com/antaur/blog/17-08/423751_6cc0d.html 0. 引言 通过之前的学习,可以在PL端创建从机模式的AXI接口IP ...

  7. EMIF接口与FPGA的互联(转)

    reference: https://blog.csdn.net/ruby97/article/details/7539151 DSP6455的EMIFA模块 之前介绍了DSP6455的GPIO和中断 ...

  8. 【iCore4 双核心板_FPGA】例程十三:基于SPI的ARM与FPGA通信实验

    实验现象: 1.先烧写ARM程序,然后烧写FPGA程序. 2.打开串口精灵,通过串口精灵给ARM发送数据从而给FPGA发送数据 ,会接收到字符HELLO. 3.通过串口精灵发送命令可以控制ARM·LE ...

  9. AM5728通过GPMC接口与FPGA高速数据通信实现

    硬件:AM5728开发板:Artix-7开发板软件:Linux am57xx-evm 4.4.19:Vivado 2015.2作者:杭州矢志信息科技有限公司邮箱:admin@sysjoint.com ...

随机推荐

  1. iptables中DNAT的配置方法

    1.一对一流量完全DNAT 首先说一下网络环境,普通主机一台做防火墙用,网卡两块 eth0 192.168.0.1  内网 eth1 202.202.202.1 外网 内网中一台主机 192.168. ...

  2. 小白也能看懂的插件化DroidPlugin原理(三)-- 如何拦截startActivity方法

    前言:在前两篇文章中分别介绍了动态代理.反射机制和Hook机制,如果对这些还不太了解的童鞋建议先去参考一下前两篇文章.经过了前面两篇文章的铺垫,终于可以玩点真刀实弹的了,本篇将会通过 Hook 掉 s ...

  3. ORACLE - 管理表空间和数据文件

    ORACLE表空间是一个逻辑分区,一个数据文件只能属于一个表空间,一个表空间可以拥有多个数据文件. 一般情况下,如果一个实例分配给多个应用使用,需要创建不同的表空间,每个用户使用自己的表空间. 一.表 ...

  4. [补档][COGS 426]血帆海盗

    [COGS 426]血帆海盗 题目 传送门:http://cogs.pro/cogs/problem/problem.php?pid=426 随着资本的扩大,藏宝海湾贸易亲王在卡利姆多和东部王国大陆各 ...

  5. hdu2108 Shape of HDU 极角排序判断多边形

    Problem Description 话说上回讲到海东集团推选老总的事情,最终的结果是XHD以微弱优势当选,从此以后,"徐队"的称呼逐渐被"徐总"所取代,海东 ...

  6. java.lang.NoSuchMethodError:android.content.Context.getDrawable

    今天在开发的时候,这个代码在源码中是可以看到的,但是在android 4.3手机上面会报错,具体错误信息和代码如下: setBackgroundDrawable(context.getDrawable ...

  7. MapReduce最大值

    package com.bw.hadoop;import java.io.IOException;import org.apache.hadoop.conf.Configuration;import ...

  8. 资金平台交易明细扩展开发-DEP

    前言 支持农垦项目中,需要增加抓取银行接口传输数据,需求有两点:一是银企平台前置机需要增加扩展中行.农行数据字段.(代理账号.代理账户名称.代理银行) 二是EAS资金模块中的交易明细查询列表界面能够显 ...

  9. macOS Sierra 10.12.6 安装u盘制作

    一.准备工作: 准备一个 8GB 或以上容量的 U 盘,确保里面的数据已经妥善备份好(该过程会抹掉 U 盘全部数据) 从这里下载苹果官方 OS X Yosemite 正式版的安装程序 (可选 AppS ...

  10. 纯CSS实现垂直居中的7种方法

    今天申请博客通过了,给大家讲讲我所看到过的纯css实现垂直居中的各种方法.为什么要把它作为第一篇文章呢?因为这是我刚开始接触前端学到的对我最有用的知识,希望大家也可以从中获益! 在CSS中实现水平居中 ...