学习目的:

(1) 熟悉SPI接口和它的读写时序;

(2) 复习Verilog仿真语句中的$readmemb命令和$display命令;

(3) 掌握SPI接口写时序操作的硬件语言描述流程(本例仅以写时序为例),为以后描述更复杂的时序逻辑电路奠定基础。

学习过程:

SPI的相关知识】

① SPI的速度比串口的快,采用源同步传输的方式,且为串行传输,应用场景不同则时序和接口名称会有不同;

② 串行flash的读写擦除命令可通过SPI接口进行通信,CPU芯片与FPGA可通过SPI接口进行通信,某些芯片的参数寄存器也可通过SPI的方式配置;

③ SPI接口说明

图1 SPI接口

SCLK:主机给从机的系统时钟信号;

SDI:主机输出给从机的数据信号;

SDO:从机输出给主机的数据信号;

CS:片选信号(此处为高电平有效);

SDIO(三线模式):主机与从机之间的双向数据总线。

DAC3283芯片与SPI有关内容】

DAC3283芯片的寄存器映射如图1所示:

图1 DAC3283芯片的寄存器映射图

从图1可知,此DAC芯片共有32个寄存器需要配置(CONFIG0~CONFIG31),且每个寄存器均为8bit。

【关于这些寄存器的配置方法】对于寄存器数量少的情况,可以直接定义几个reg型变量,然后用这些reg变量初始化那些待配置的寄存器;而对于像本例这样有如此多的寄存器需要配置,则需通过FPGA的ROM或RAM完成寄存器的初始化,即:先将配置参数写到FPGA的ROM或者RAM中,然后再通过FPGA把这些参数从ROM或者RAM中读出并写入到外部芯片的寄存器中去。在本例中,是通过SPI接口写入到DAC3283芯片的。

DAC3283芯片的SPI接口时序】

图2 SPI的写时序图

图3 SPI的读时序图

首先,对图2、图3中的几个信号名称作介绍。SCLK是由FPGA送给DAC芯片的时钟信号;SDENB是串行接口的使能信号(相当于片选信号),只有当它为低电平时,SPI的读写才有效;对于“三线模式”的SPI,SDIO是一个双向的数据线,负责数据的读写数据传输;对于“四线模式”的SPI,SDIO也是一个双向的数据线,但ALARM_SDO是一个只读数据线,仅负责DAC芯片输出数据的传输。数据在SCLK的上升沿时刻写入DAC芯片,在SCLK的下降沿时刻从DAC芯片中读出。

然后,介绍一下SPI每次传输的数据内容。本例中,SPI采用的是先传高位后传低位的串行传输方式,每次传输16bit,其中,前8bit构成SPI的指令周期,后8bit构成SPI的数据周期。在前8bit中,rwb(R/W)是读/写控制信号,即:若rwb为高电平时,此条指令为读指令;若rwb为低电平时,此条指令为写指令。N1、N0指明每帧传输的数据字节数(范围为1~4字节,不包含前面的那个指令字节),A3…A0是DAC芯片各寄存器的地址。

SPI接口的状态机】

 
   

图4 DAC芯片寄存器初始化操作状态机(概念模型)

IDLE是起始状态(默认态),work_en是从外部输入的启动使能信号(高电平有效);WAIT是等待状态,在本例中,等待8个时钟周期后(wait_cnt[3] == 1'b1)即进入到READ_MEM状态(读存储器状态),直接读取RAM中的数据;WRITE_REG是写寄存器状态,将32个16bit位宽的数据通过串行移位的方式送给DAC芯片的寄存器,移位完1个16bit位宽的数据后(shift_cnt == 4'd15 && pose_flag == 1'b1 && data_end != 1'b1)就回到WAIT状态,然后重新等待8个时钟周期,重新执行READ_MEM状态和WRITE_REG状态,直到32个数据全都读写完毕后才进入STOP状态(shift_cnt == 4'd15 && pose_flag == 1'b1 && data_end == 1'b1),拉高conf_end信号。

【设计步骤】

(1) 写spi_ctrl.v文件,首先写分频计数器,将50MHz的系统时钟分频为1MHz作为SPI的时钟spi_clk(一般是50~60MHz,但此处仅是演示实验,用1MHz即可),同时,产生clk_p和clk_n两个相位相反、频率为1MHz的reg信号,clk_p是正相时钟信号,用以触发脉冲标志信号pose_flag(标志SPI时钟信号上升沿的到来),clk_n是反相的时钟信号,用作spi_clk,送给SPI当作时钟使用,以上共需写4个always语句块。

(2) 建立一个16bit x 32的单口RAM IP核(仅读不写),并例化到spi_ctrl.v中,完成mif文件的编辑和拷贝。

(3) 声明状态机变量,写状态机(两段式),包括等待状态下的计数器、读RAM的地址产生模块(1个系统时钟周期读出1个数据)、串行移位寄存器(左移,移出最高位)、移位操作的计数器、data_end信号控制模块、数据输出模块、片选信号控制模块、conf_end信号控制模块以及状态跳转模块等部分。

(4) 写testbench文件和run.do文件,运行仿真并分析仿真结果(跑300us)。对testbench文件的要求如下:①能使用$readmemb命令读出dac_ini_16x32.mif文件中的数据;②能在rec_spi任务块中实现对SPI传输数据的回收,并与dac_ini_16x32.mif文件中的数据进行校对,然后用$display命令显示校对结果和数据信息。

【代码实现】

(1)设计一个计数分频模块,用50MHz的系统时钟产生1MHz的时钟信号给SPI读/写操作使用,同时产生clk_p和clk_n两个相位相反、频率均为1MHz的信号:

同时,产生一个标志clk_p上升沿的标志信号pose_flag,用它统一系统的全局时钟:

【注意事项】尽量不要使用分频产生的clk_p或clk_n当作always块的触发条件!原因:时钟信号在很大程度上决定了整个设计的性能和可靠性,应尽量避免使用FPGA内部逻辑产生的时钟,因为它很容易导致功能或时序出现问题,内部逻辑产生的时钟信号容易出现毛刺(布线用线的质量较差),影响信号质量,同时,组合逻辑电路固有的延时也容易导致时序问题。详细的解说请见特权的《深入玩转FPGA》一书的P59。

(2)RAM IP核的创建和例化:

图5 RAM IP核的参数配置

图6 去掉q端寄存器

图7 新建和添加mif文件

图8 勾选例化文件

例化到spi_ctrl.v文件中:

(3)声明状态变量和状态参数,写状态机:

状态跳转控制:

① 写状态机写到WAIT状态时,发现需要产生wait_end信号,而wait_end信号是由计数等待8个时钟周期后产生的,故先需要设计WAIT状态等待计数模块:

然后,用设计wait_end信号产生模块:

② 写状态机写到READ_MEM状态时,发现需要先将RAM中的数据读出来,故先需设计产生读RAM地址的模块:

③ 写状态机写到WRITE_REG状态时,发现先要将从RAM读出来的数据缓存起来(通过shift_buf缓存),然后逐比特地通过sdi线送给DAC芯片(串行移位寄存器):

然后,设计模块产生移位完成的标志信号shift_end:

然后,设计SPI接口的数据输出模块、片选信号控制模块以及时钟信号产生模块:

数据逐比特地送给spi_sdi接口,每帧传输16bit的数据,当传输完32个16bit的数据后,需要产生一个data_end标志信号,标志所有数据已经传输完毕:

当传输完32个16bit的数据时,也即完成了DAC芯片32个寄存器的配置工作,故需要产生一个conf_end标志信号,标志配置操作的完成:

Testbenchrun.do

Testbench文件:

① 用文件控制任务$readmemb读出dac_ini_16x32.mif文件中的数据,并用这些数据初始化存储器mif_data(reg [15:0] mif_data[0:31]):

② 计一个名为spi_check的任务,用它回收spi通信的数据,并将其与dac_ini_16x32.mif文件中的数据进行校对,如果数据一致则输出数据的索引和具体内容,否则提示“SPI write is error!”:

run.do文件:

【仿真结果及分析】

图9 transcript窗口的信息1

图10 transcript窗口的信息2

如图9、图10所示,Testbench从SPI接口回收的数据与mif文件中的数据一致,由此可见SPI数据传输的正确性。

图11 状态机视图

如图12所示,是SPI仿真波形的整体图:

图12 仿真波形图1

如图13所示,spi_clk的上升沿对准spi_sdi数据的中心,满足DAC芯片SPI写时序的要求,即:数据在时钟信号上升沿到来的时候写入DAC芯片。

图13 仿真波形图2

如图14所示,展示了状态机跳转到STOP状态(10000)及data_end上升沿的出现。

图14 仿真波形图3

图15 仿真波形图4

由图15可知,在WRITE_REG状态下,片选信号spi_csn低电平状态的持续时间约为16us,而spi_clk的周期是1us,故由此可知SPI每次移位传输占用了16个SPI时钟周期,这与代码中设计的每帧传输16bit数据的设想是一致的。

转载:https://www.cnblogs.com/huangsanye/p/5256494.html

SPI和RAM IP核的更多相关文章

  1. 第7讲 SPI和RAM IP核

    学习目的: (1) 熟悉SPI接口和它的读写时序: (2) 复习Verilog仿真语句中的$readmemb命令和$display命令: (3) 掌握SPI接口写时序操作的硬件语言描述流程(本例仅以写 ...

  2. 用嵌入式块RAM IP核配置一个双口RAM

    本次设计源码地址:http://download.csdn.net/detail/noticeable/9914173 实验现象:通过串口将数据发送到FPGA 中,通过quartus II 提供的in ...

  3. 自定义AXI总线形式SPI接口IP核,点亮OLED

    一.前言 最近花费很多精力在算法仿真和实现上,外设接口的调试略有生疏.本文以FPGA控制OLED中的SPI接口为例,重新夯实下基础.重点内容为SPI时序的RTL设计以及AXI-Lite总线分析.当然做 ...

  4. IP核——RAM

    一.Quartus 1.打开Quartus ii,点击Tools---MegaWizard Plug-In Manager 2.弹出创建页面,选择Creat a new custom megafunc ...

  5. 7系列高速收发器总结 GTP IP核使用篇

    上一篇7系列收发器博文讲解了GTP IP核的基本配置,本文继续分析如何将它使用起来.生成IP核后打开example design,先看看工程中包含的文件结构. 顶层文件下包含了gtp ip核系统顶层文 ...

  6. Vivado中xilinx_BRAM IP核使用

     Vivado2017.2 中BRAM版本为 Block Memory Generator Specific Features  8.3 BRAM IP核包括有5种类型: Single-port RA ...

  7. EMAC IP 核

    在有线连接的世界里,以太网(Ethernet)无所不在.以太网具有各种速度模式.接口方式.以及灵活的配置方式.现在的以太网卡都是10/100/1000Mbps自适应网卡.以太网的物理层(PHY)通常使 ...

  8. IP核——FIFO

    一.Quartus 1.打开Quartus ii,点击Tools---MegaWizard Plug-In Manager 2.弹出创建页面,选择Creat a new custom megafunc ...

  9. ARM架构授权和IP核授权有什么不一样啊?

    比如,华为分别拿到这2个授权,能做的有什么区别啊? 匿名 | 浏览 2976 次 推荐于2016-06-09 02:43:35   最佳答案   一个公司若想使用ARM的内核来做自己的处理器,比如苹果 ...

随机推荐

  1. Java远程方法协议(JRMP)

    Java远程方法协议(英语:Java Remote Method Protocol,JRMP)是特定于Java技术的.用于查找和引用远程对象的协议.这是运行在Java远程方法调用(RMI)之下.TCP ...

  2. java 从spring容器中获取注入的bean对象

      java 从spring容器中获取注入的bean对象 CreateTime--2018年6月1日10点22分 Author:Marydon 1.使用场景 控制层调用业务层时,控制层需要拿到业务层在 ...

  3. 【PMP】财务测量指标ROI、PBP、NPV、IRR、BCR

    各指标说明: 1.投资回报率(ROI) 定义:是指通过投资而应返回的价值,即企业从一项投资活动中得到的经济回报. 1.1 年平均利润相等的情况下 公式:ROI=年平均利润/投资额 案例: 1.2 年平 ...

  4. .NET/C#中对自定义对象集合进行自定义排序的方法

    一个集合可否排序,要看系统知不知道排序的规则,像内建的系统类型,int ,string,short,decimal这些,系统知道怎么排序,而如果一个集合里面放置的是自定义类型,比如自己定义了一个Car ...

  5. linux下挂载VHD等虚拟磁盘文件

    1.RAW格式虚拟磁盘 linux下可以直接挂载raw格式的虚拟磁盘镜像文件. 例如,这里先用dd命令创建一个文件,然后将其格式化为ext4格式(只有一个分区),然后挂载到/mnt目录. 下面的raw ...

  6. loadrunner 脚本开发-参数化之将内容保存为参数、参数数组及参数值获取

    转自:http://blog.sina.com.cn/s/blog_13cc013b50102v49c.html(查看原文) 在VuGen中默认使用{}的字符串称为参数 注意:参数必须在双引号中才能用 ...

  7. Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener. ...nested exception is java.lang.NoSuchMethodError:

    ssh 中,项目部署到服务器的时候,出现这样的奇葩的事情: 21-Oct-2017 11:27:15.953 INFO [localhost-startStop-1] org.apache.catal ...

  8. 转:ArcEngine10.0+VS2010+MFC 扫盲贴 .

    项目用vc6.0+MapObject写的,现在却要升级成AE10,研究了好多天的AE10.0和c++,中间的曲折也不想多说了,废话少数,下面是实现ArcEngine基本功能的,仅供参考,如能帮到同仁们 ...

  9. iOS TableView多级列表

    代码地址如下:http://www.demodashi.com/demo/15006.html 效果预览 ### 一.需求 TableView多级列表:分级展开或合并,逐级获取并展示其子级数据,可以设 ...

  10. android 发送短信的两种方式,以及接收报告和发送报告

               android发送短信,以及接收报告和发送报告          android中发送短信其实有两种方式,这个和打电话类似,大家可以了解一下:    一.调起系统发短信功能    ...