上一篇文章我们介绍了DAC81416的配置过程,这一篇我们就用Verilog代码具体实现这个过程,这一篇的代码具有普遍性,以后所有DA/AD的配置代码都可以在本文所展示的代码上进行修改获得。这里先给出源代码链接和一个通用fifo(作为子模块)的代码链接。这是我在FPGA教学系列文章中第一次展示代码,所以我会以设计者的角度来还原代码编写时的设计步骤,也就是设计思想的展示,希望能给初学者们一个参考,当然仅仅是参考,不代表萌新们一定要这样做,或许你会觉得我这篇文章写得很啰嗦,那就请无视文章直接下载源代码吧。后续的文章中除非特定情况,否则不会再有这样的设计思想展示。

一、端口的定义

我们对设计需求的建立过程就是我们的模块端口的定义过程。一般情况下,我们在编写代码时,先要整体考虑我们的需求,也就是我们的目的。这里,我们知道我们的目的就是通过SPI配置DAC81416并且配置完成之后再发送数据,所以我们除了定义和DAC通信的端口外,还要定义用户端的端口,用户端的端口可以根据实际情况自定义(用户可能是自己的其他模块,也可能是别人的模块),这里给出的只是我定义的形式,不同的读者有不同的定义形式,只要你觉得好用,符合你自己的思维习惯或者符合别人的接口标准,就行。

图1 SPI接口的端口

这里需要注意的是,端口定义的初期我们不一定能想得面面俱到,事实上,我们只需给出一个端口的大致定义即可,很多具体的细节反而是在后面正式编写代码的过程中进行适当添补和删减得到的。

二、过程的描述

端口定义好之后,我们要考虑清楚两个过程。第一个过程是站在用户角度,用户怎么使用我们的模块;第二个过程是我们要做哪些操作来满足用户的使用。

用户使用的过程:用户让configStart有效之后等待ready,用户在收到ready有效之后无效configStart信号完成握手,这时就可以进行数模转换的数据的输出,数据的输出方法就是在dout_en有效的节拍内输出dout_num和dout_data,分别表示输出通道和数模转换的数据,这个过程中可以只输出一个通道一次,也可以输出一个通道多次,也可以一次性输出几个通道,根据dout_en的长短和dout_num的值来决定。之后,用户有效complete,完成本次输出,下次输出时用户需再次有效configStart并等待ready,重复上述过程。

本模块的操作过程:本模块在确认第一次configStart有效之后进行初始化配置操作,但是如果不是第一次发送数据,configStart有效时或许本模块还处于发送数据状态,所以要等到所有数据发送完毕之后再进行配置操作,配置操作完成之后才能有效ready。之后,本模块就等待dout_en有效时截取dout_num和dout_data,获取了输出端口和输出数据之后,就进行配置DACn Register的操作来完成数据的发送,这个过程中或许dout_en连续有效,表示连续单端口输出或一次性多端口输出,所以必须缓存dout_num和dout_data。收到complete之后就该结束这一轮的发送过程,但是或许本模块在收到complete之后缓存的数据还没有发送完,这时也需要对complete进行缓存。在收到complete之后和下一次初始化配置完成之前就必须无效ready,以防用户误以为本模块已经准备好了。

这里需要注意的有两点:第一,与端口定义一样,上面的两个过程同样不是最初就能面面俱到的,本人强烈建议初学者把这两个过程用文字或图表描述出来,哪怕考虑得不完美,这个训练很有必要。写出这两个过程之后,我们就知道代码中大概需要包括哪些子模块、以及主状态机如何初步定义和跳转,在后续写代码的过程中我们就会很有头绪。正式写代码的过程中再反过来补充这两个过程,完善对子模块和状态机的细节问题。第二,有时候我们写的是中间模块,这就要考虑到上级用户、下级用户甚至是总线级用户的使用过程,有多少个用户,我们就要写出多少个过程,哪怕用户给出的是标准接口,我们也最好把这个过程写出来帮助我们理清头绪。

三、状态转移图

想清楚了过程之后,状态机就很容易定义了,不同的人定义的状态机可能都不一样,这里只是给出了我定义的一种,仅供参考。

图2 SPI接口的状态转移图

上图中, IDLE是初始状态,CFIG是配置状态,CFNT(ConfigNext)是判断配置是否完成的状态,WTDT(WaitDout)是等待输出数据状态,DOUT是输出数据状态,DTNT(DoutNext)是判断输出是否完成状态,DONE就是最终的完成状态。这一步的设计技巧是,我们在写状态转移图时,没必要精确写出转移条件,把转移条件用文字描述即可,具体的转移条件写代码时根据情况设置。同前两步一样,状态转移图也不是一开始就完美无缺的,状态的增减和条件的改变在设计中是经常发生的。

四、其他设计细节思考

到这步的时候,我们可以把自己考虑到的设计细节(任何在头脑中灵光一现的都可以,无论对错都可以)列出来,在这里我仅写5条示范下。当然,如果暂时没有考虑到任何细节就略过这步,任何时候只要有灵感都可以记录下来。

1、我们可以设计一个频率变化的SPI输出时钟,这样有利于以后的调试。

2、配置DAC的数据是固定数据,可以例化一个ROM。

3、缓存就用FIFO。

4、因为对DAC的每次操作都是24位数据,所以应该设置一个模24的计数器。

5、普通模式下不用的端口信号全部输出0或1(保证其无效就行)。

准备工作到此结束。至于具体编写Verilog代码时中间的信号线和寄存器,都是边写边定义的,每个always语句块怎么给变量赋值,也是边写边考虑的。至于时序问题,先不用考虑太多,我会专门写一篇文章讲,代码写多了之后自然就知道该如何避免时序上踩雷,事实上,很多时序问题反而是在仿真和调试过程中发现并调整的,对于新手来说,最开始写代码时真不用特别考虑。

编写testbench,用modelsim把本文开头给出的源代码进行仿真,可以看到SDI满足SCLK下降沿采样,CSN满足低电平有效。关于如何编写testbench,如何使用modelsim的基本功能,我会另外写一篇文章,就以本篇的源代码为例子来探讨。

图3 modelsim仿真的spi波形

本人水平有限,如有错误,欢迎留言指正。

SPI接口的FPGA实现(三)——Verilog代码实现SPI接口相关推荐

  1. FPGA驱动OLED Verilog代码 (五)------ 动态显示字符

    一.概述 前面已经介绍了向RAM中写入静态字模数据来显示静态的字符和汉字.接下来实现动态显示字符在OLED屏的不同位置. 动态显示字符的核心就是从ROM中读取字符的字模,但取出来的字模数据如果直接写进 ...

  2. 【FPGA】用Verilog代码实现无源蜂鸣器驱动实验

    目录 一.理论部分 1.蜂鸣器概述 2.驱动原理 3.实验目标 二.模块框图 三.波形图 1.时钟与复位信号 2.计数器 (1)0.5s计数器 (2)音调频率计数器 (3)分频计数器 (4)频率变量最 ...

  3. SPI接口的FPGA实现(二)——配置DAC

    这一篇主要结合DAC81416的datasheet来进一步阐述如何配置DAC.先附上DAC81416的datasheet的链接. 一.datasheet概述 如果自己不做电路板,DAC81416的da ...

  4. UART接口的FPGA实现(一)——UART接口的相关基础知识

    UART系列文章先介绍UART的基础知识,然后自己动手写Verilog代码实现这个接口并进行测试,最后介绍Xilinx的AXI-uartlite IP核.本系列文章编写时参考了乔庐峰老师编写的Veri ...

  5. 升级至4K超高清12G-SDI接口时需要考虑的三件事

    升级至4K超高清12G-SDI接口时需要考虑的三件事 1. 传输接口:基于SDI或IP的视频(10G以太网) 2. 传输介质:同轴电缆还是光纤? 3. 传输速度:3G-SDI还是12G-SDI? 1. ...

  6. FPGA接口_N25Q128型号的spi flash驱动verilog代码编写

    # N25Q128型号的spi flash驱动verilog代码编写 提示:使用正点原子达芬奇pro做的小例子,由于教程中无flash的读写,因此撰写记录 文章目录 # N25Q128型号的spi f ...

  7. fpga驱动oled iic显示代码_【接口时序】6、IIC总线的原理与Verilog实现

    欢迎FPGA工程师加入官方微信技术群 点击蓝字关注我们FPGA之家-中国最好最大的FPGA纯工程师社群 一. 软件平台与硬件平台 软件平台: 1.操作系统:Windows-8.1 2.开发套件:ISE ...

  8. 04【Verilog实战】SPI协议底层硬件接口设计(附源码RTL/TB)

    脚  本:makefile 工  具:vcs 和 verdi 写在前面 这个专栏的内容记录的是个人学习过程,博文中贴出来的代码是调试前的代码,方便bug重现. 调试后的程序提供下载,[下载地址] 发现 ...

  9. FPGA纯verilog代码读写N25Q128A QSPI Flash 提供工程源码和技术支持

    目录 1.N25Q128A芯片解读 2.N25Q128A读写时序 3.整体设计思路架构 4.verilog读写Flash驱动设计 5.verilog读写Flash控制器设计 6.FIFO缓存设计 7. ...

最新文章

  1. LeetCode 26 删除有序数组中的重复项
  2. php中文网 日历,php小型日历类库
  3. Windows 10 计算器全新升级,支持三角函数运算
  4. 2-7 微信摇一摇_实现分析
  5. 11.17 shell特殊符号cut命令,sort_wc_uniq命令,tee_tr_split命令,shell特殊符号
  6. Hadoop学习笔记(二):MapReduce的进度和状态
  7. HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
  8. 自动驾驶仿真:Carsim、NI和VTD联合仿真课题一
  9. 教学用计算机房活荷载,计算机机房承重标准及承重计算方法
  10. 【eoeAndroid社区索引】Android控件知识汇总
  11. CRMEB多商户商城系统主要功能及技术亮点
  12. 腾讯云IM购买和接入指南
  13. 全球定位经纬度的方法现在是GPS等系统定位,以前是指南针罗盘六分仪
  14. java 批量生成条形码,打包zip(springboot)
  15. win7计算机资源管理器卡住,如何解决win7系统资源管理器已停止工作的问题
  16. 论文caj转换为word
  17. 基于jeecgboot的flowable流程增加节点表单的支持(二)
  18. 【Cocos Creator 实战】01 - 如何做一款简单的拼图游戏
  19. 使用@Lazy解决循环依赖问题
  20. CSS齿轮转动加载动画

热门文章

  1. 配置用友UAP平台(NC65)
  2. PackagesNotFoundError: The following packages are not available from current channels 解决办法
  3. CSS中隐藏页面元素的几种方式和区别
  4. LINUX下看门狗的使用
  5. SQlite增删改查
  6. Unity_四元素Quaternion
  7. 马建强老师谈如何做好PPT演讲演示
  8. 职场“老好人”,难怪你收入低
  9. 通俗易懂理解死锁以及如何避免死锁
  10. PHP7——语言基础