SPI接口的Verilog语言实现 - 图文
更新时间:2024-01-19 22:26:01 阅读量: 教育文库 文档下载
电子与电气工程系
课程设计、专题(综合)实验报告
课题名称__串行接口IP核的设计与验证(spi)_
专 业____ 电子信息工程________ 班 级_____ 08电子1班__________ 学 号__0806012103_ 0806012104_ 姓 名___ 高江柯____吴冠雄__ ______ 成 绩________________________ 指导教师_______袁江南____________
2011年 6 月 15 日
串行接口IP核的设计与验证(SPI)
(FPGA作为主机) 一、 实验目的:
通过本实验的学习,使学生掌握使用VHDL 设计一个实用数字系统的能力,以及单片机串行接口编程等知识,训练 VHDL以及单片机的编程与综合使用能力,培养工程设计的基本技能,为今后毕业设计以及实际工作奠定基础。
二、 实验原理
SPI 接口是在 CPU 和外围低速器件之间进行同步串行数据传输,在主器件
的移位脉冲下,数据按位传输,高位在前,地位在后,为全双工通信,数据传输速度总体来说比I2C 总线要快,速度可达到几Mbps。
SPI 接口是以主从方式工作的,这种模式通常有一个主器件和一个或多个从 器件,其接口包括以下四种信号:
(1)MOSI –主器件数据输出,从器件数据输入 (2)MISO –主器件数据输入,从器件数据输出 (3)SCLK – 时钟信号,由主器件产生
(4)/CS –从器件使能信号,由主器件控制
在点对点的通信中,SPI 接口不需要进行寻址操作,且为全双工通信,显得简单高效。
SPI接口在内部硬件实际上是两个简单的移位寄存器,传输的数据为8位,在主器件产生的从器件使能信号和移位脉冲下,按位传输,高位在前,低位在后。下图所示,在 SCLK 的下降沿上数据改变,同时一位数据被存入移位寄存器。
三、 实验步骤:
1、
2、 3、 4、 5、 6、
查找关于SPI的资料,认识理解SPI。
根据SPI传输数据的时序图构建出SPI的框图。
利用自顶向下的方法根据框图分模块进行程序的编写。 把各模块连接构成完整的SPI传输系统。 进行仿真验证。
在康芯开发板上验证此SPI系统收发及中断功能是否正常。(由于时间原因其步未能完成)
四、 设计过程:
模块1:
输入说明:
data7[7..0] : FPGA写数据到RAM的输入口。 enable : 为输入使能。 reset : 复位。 clk : 输入时钟。
contr_addr[5..0]: FPGA写数据到RAM的地址的最大值,即写入RAM
中数据的个数。
feedback : SPI系统发送完数据的反馈,提示FPGA又可以重
新写数据到RAM,然后发送。
输出说明:
wr_en : 控制RAM写使能。
wr_addr : 写数据到RAM的地址控制,写一数据地址加一。 wr_clock : RAM写数据时钟,上升沿有效。 fullflag : RAM写满的标志。 data_out[7..0] : RAM中写入的数据。
模块说明:
FPGA通过SPI发送数据,数据必须要有个缓存阶段。此设计中是利用RAM作为缓存。该模块就是数据写入RAM的控制器,并提示FPGA开始发送数据及发送多少个数据。SPI发送完数据后提示FPGA重新写数据到RAM继续发送。
仿真时序图:
模块2:
输入说明:
data[7..0] :输入RAM的数据。
wraddress[5..0] :RAM写地下输入,写一数据地址加一。 wren :RAM写使能
rdaddress[5..0] :RAM读地址输入,读一数据地址加一。 rden :RAM读使能
wrclock :RAM写数据时钟,上升沿有效。 rdclock :RAM读数据时钟,上升沿有效。
输出说明:
q[7..0] :读RAM数据输出口。
模块说明:
这是双通道的RAM,此设计中需要定制2个容量为64BIT的,能进行数据的读写。需注意的数据的读写不能同时操作。
模块3:
输入说明:
clk :系统时钟。
ramindata[7..0] :输入需要发送的数据。 Cpuwr :
Miso :主机输入从机输出。 Reset :复位。 RFirq :开始发送。
Fullflag :RAM存满,请求开始发送标志。 Addr_num[5..0] :需要发送数据的个数。 输出说明:
feedback :发送完数据后反馈给RAM控制器,请求重新写入RAM数据
发送。
outdata[7..0] :接收到从机发出的数据,用于测试。 mosi :主机发出的移位数据,从机输入。 Irq :发送完中断主求。
CSN :从机选择控制,低电平有效。 SCK :主机从机发送移位数据时钟。
SendAddr[5..0] :RAM读地址控制,读取RAM中的数据进行发送。 SendRDen :RAM读使能。
ReceiveData[7..0] :接收到的数据,用于写入RAM。
ReceiveAddr[5..0] :接收到的数据写入RAM的地址控制。
SendramClk :读取RAM中的数据用于发送的时钟,上升沿有效。 ReceiveClk :接收到的数据写入RAM中的时钟控制,上升沿有效。 ReceiveWen :接收到数据写入RAM使能。 CE:
Sendfinishtest :发送结束标志。
ram_rd :整个数据接收完后,读取RAM中数据使能。
ram_rd_clk :整个数据接收完后,读取RAM中数时钟,上升沿有效。 ram_rd_addr[5..0] :整个数据接收完后,读取RAM中数据的地址控制。
模块说明:
此模块是整个系统的核心部分,控制着SPI的收发。 其整个流程大致如下:
RESE初始化 等待 准备 Y N fullflag=1 N ReadReging=0 Y 开始发送 同时接收 发送接收第一个数据 发送接收中间数据 N sendFinishByte= SendByteNum-1 Y Irq=1 申请中断 sendfilish=1 feedback 读取RAM中收到的数据 ReadReging=1 N ReadReging=0 Y 结束
具体的程序写法:
其收发过程都是通过状态机实现的。状态机容易构成性能良好的同步时序逻辑模块,而且能很大限度的消除毛刺现象。 读取第一个数据(4个状态):
标记,处于发送态 产生读RAM脉冲态 准备发送态 读取第一 个数据态
开始发送接收(17个状态,采用顺序编码): 5'b00000: CSN=1'b0; 片选从机,低电平有效 SCK=1'b0; 拉低SPI时钟线,主机发送数据最高位 mosi=senddata[7]; 读取数据最高位放到数据线MOSI发送 SendRDen=1'b1; 读取发送数据使能 SendramCLK=1'b0; 拉低读RAM时钟线 bitcounter=bitcounter+5'b1; 5'b00001: SCK=1'b1; 拉高SPI时钟线,主机接收从机发出数据最高位 StatusReg0[7]=miso; 存取最高位数据
SendramCLK=1'b1; 拉高读RAM时钟线,产生上升沿读RAM bitcounter=bitcounter+5'b1; 5'b00010: SCK=1'b0; 拉低SPI时钟线,主机发送数据次高位数据 mosi=senddata[6]; 读取数据次高位放到数据线MOSI发送
bitcounter=bitcounter+5'b1;
5'b00011: SCK=1'b1; 拉高SPI时钟线,主机接收从机发出数据次高位 StatusReg0[6]=miso; 存取次高位数据 ramsendtemp=ramindata; 读取RAM中下一个数据 bitcounter=bitcounter+5'b1;
5'b00100:
SCK=1'b0; 拉低SPI时钟线,主机发送数据的第五位 mosi=senddata[5]; 发送数据第五位 SendramCLK=1'b0; 拉低读RAM时钟线 SendRDen=1'b0; 关闭读RAM使能 SendAddr=SendAddr+6'b1; 读RAM地址加一 bitcounter=bitcounter+5'b1; 5'b00101: SCK=1'b1; StatusReg0[5]=miso; bitcounter=bitcounter+5'b1; 5'b00110: SCK=1'b0; mosi=senddata[4]; bitcounter=bitcounter+5'b1; 5'b00111: SCK=1'b1;
StatusReg0[4]=miso; bitcounter=bitcounter+5'b1; 5'b01000: SCK=1'b0; mosi=senddata[3]; bitcounter=bitcounter+5'b1; 5'b01001: SCK=1'b1; StatusReg0[3]=miso; bitcounter=bitcounter+5'b1; 5'b01010: SCK=1'b0;
mosi=senddata[2]; bitcounter=bitcounter+5'b1; 5'b01011: SCK=1'b1; StatusReg0[2]=miso; bitcounter=bitcounter+5'b1; 5'b01100: SCK=1'b0; mosi=senddata[1]; bitcounter=bitcounter+5'b1; 5'b01101: SCK=1'b1;
StatusReg0[1]=miso; bitcounter=bitcounter+5'b1; 5'b01110:
接收从机发出的数据第五位 主机发送数据第四位 接收从机发出的数据第四位
主机发送数据第三位 主机接收从机发出的数据第三位 主机发送数据第二位
主机接收从机发送的数据的第二位 主机发送数据的次低位 主机接收数据的次低位
SCK=1'b0; mosi=senddata[0]; 主机发送数据的最低位 bitcounter=bitcounter+5'b1; 6'b01111: SCK=1'b1;
StatusReg0[0]=miso; 主机接收数据的最低位
bitcounter=bitcounter+5'b1; senddata=ramsendtemp; 6'b10000: SCK=1'b0; bitcounter=5'b0;
发送接收中间数据态(18个状态,采用顺序编码):
5'b00000: SCK=1'b0;
ramdReceivetemp=StatusReg0; 主机存储接收到的第一个数据,并准备
写入RAM
sendFinishByte=sendFinishByte+6'b1; 发送数据个数加一 receiveByte=receiveByte+6'b1; 接收数据个数加一
mosi=senddata[7]; 主机发送中间数据最高位 SendramCLK=1'b0; SendRDen=1'b1; bitcounter=bitcounter+5'b1;
5'b00001: SCK=1'b0; SendramCLK=1'b1;
bitcounter=bitcounter+5'b1;
5'b00010: SCK=1'b1; StatusReg0[7]=miso; 主机接收从机发出的数据的最高位 bitcounter=bitcounter+5'b1;
5'b00011: SCK=1'b0; mosi=senddata[6]; 主机发送中间数据次高位
ramsendtemp=ramindata; bitcounter=bitcounter+5'b1;
读取RAM,作为下一个发送数
5'b00100: SCK=1'b1;
StatusReg0[6]=miso; 主机接收从机发出数据的次高位 SendAddr=SendAddr+6'b1; 读RAM地址加一
SendramCLK=1'b0;
SendRDen=1'b0;
bitcounter=bitcounter+5'b1;
5'b00101: SCK=1'b0;
mosi=senddata[5]; ReceiveCLK=1'b0; ReceiveWen=1'b1; bitcounter=bitcounter+5'b1;
5'b00110: SCK=1'b1;
StatusReg0[5]=miso; bitcounter=bitcounter+5'b1;
5'b00111: SCK=1'b0;
mosi=senddata[4]; ReceiveData=ramdReceivetemp; bitcounter=bitcounter+5'b1;
5'b01000: SCK=1'b1;
StatusReg0[4]=miso; bitcounter=bitcounter+5'b1; ReceiveCLK=1'b1; (为
5'b01001: SCK=1'b0; mosi=senddata[3]; bitcounter=bitcounter+5'b1; ReceiveCLK=1'b0;
主机发送中间数据第五位
拉低写数据到RAM时钟 RAM写数据使能 主机接收从机发出的数据第五位 主机发送中间数据的第四位
准备好写入的数据(在时钟上升沿到来前, 将数据放到总线上) 主机接收从机发出数据的第四位 将拉收到的上一个数据第一次写入RAM 了安全,每个数据写两次) 5'b01010: SCK=1'b1; StatusReg0[3]=miso; bitcounter=bitcounter+5'b1;
ReceiveCLK=1'b1; 第二次写入(为了安全,每个数据写两次)
5'b01011: SCK=1'b0; mosi=senddata[2]; bitcounter=bitcounter+5'b1; ReceiveAddr=ReceiveAddr+6'b1; ReceiveCLK=1'b0; ReceiveWen=1'b0; //取消写ram信号
5'b01100:
SCK=1'b1;
StatusReg0[2]=miso; bitcounter=bitcounter+5'b1;
5'b01101: SCK=1'b0; mosi=senddata[1]; bitcounter=bitcounter+5'b1;
5'b01110: SCK=1'b1; StatusReg0[1]=miso; bitcounter=bitcounter+5'b1;
5'b01111: SCK=1'b0; mosi=senddata[0]; bitcounter=bitcounter+5'b1;
6'b10000: SCK=1'b1; StatusReg0[0]=miso; bitcounter=bitcounter+5'b1;
6'b10001: SCK=1'b0;
bitcounter=5'b0; sendFinishByte=sendFinishByte+6'b1; 接收数据个数加一 ramdReceivetemp=StatusReg0; 主机缓存接收到的数据
senddata=ramsendtemp; 主机把读到的下一个数据拉到发生寄 存器,准备发送 receiveByte=receiveByte+6'b1;
发送最后一个数据(21个状态,采用顺序编码):
前面17个状态与接收发送第一个数据,中间数据基本相同。故不作具体陈述。
6'b10010: CSN=1'b1; bitcounter=bitcounter+5'b1;
ReceiveCLK=1'b0;
6'b10011:
ReceiveCLK=1'b1; bitcounter=bitcounter+5'b1;
6'b10100:
ready=1'b0; feedback=1'b1; senden=1'b0; sendfilish=1; receiveByte=receiveByte+6'b1; ReceiveAddr=6'b0; ReceiveCLK=1'b0; ReceiveWen=1'b0; ReceiveReady=1'b1;
bitcounter=bitcounter+5'b1;
6'b10101: bitcounter=5'b0;
feedback=1'b0;
顶成框图:
取消选择从机使能 接收到数据第二次写入RAM(为了安 全,每个数据写两次) 发送接收完准备取消
反馈给RAM控制器,可以重新写数据 取消发送使能 发送完成标志 接收数据加一 接收地址清0 取消写ram信号
反馈信号清0
仿真时序图:
仿真结果说明:
仿真通过设置contr_addr=4来写五个数据(11,12,7,15,16)到RAM,然后发送。
五、 设计中遇到的问题及解决办法:
1、 控制RAM写数据的时钟时,忽视了Verilog语言的语句执行特 导致RAM中总是写不进去数据。 wr_clock=1'b0;
wr_clock=1'b1; 第一次写入 wr_clock=1'b0;
wr_clock=1'b1; 第二次写入
这样执行后的结果为wr_clock=1'b1,一直为上高平,并不会有两个上升沿。
最好的解决方法就是使用状态机。 2’b00: wr_clock=1'b0;
2’b01: wr_clock=1'b1; 第一次写入 2’b10: wr_clock=1'b0;
2’b11: wr_clock=1'b1; 第二次写入
2、 处理反馈信号feedback与存满信号fullflag的逻辑关系时,遇到 了些麻烦,最终巧妙的运用异或解决了问题。
a=(~feedback)&fullflag0;
b=feedback&(~fullflag0); fullflag=a|b;
3、 在定制FIFO时遇到很大的问题,如数据不能按照严格的时序进出
FIFO,而且有些数据还不能写进FIFO,经过多方面调试改写还是没能解决。最终只能放弃FIFO,改用RAM,外加个控制器就可以了。
六、 设计心得与体会:
1、这次设计花了我四天多时间完成,做之前单纯的以为SPI不过就是写几个简单的移位寄存器外加个时钟就可以了,却完全忽视了SPI具有严格的时序要求及数据发送接收存储问题。SPI不是只发送接收一个八位数据就可以了的,它应该具有强大的信息交换传输功能。
2、仿真时序很不好把握,以后尽量少用Quartus II自带仿真器,要多多学习MODOSIM。 3、Verilog HDL自学了一段时间,第一次用来编写一个完整的系统。和VHDL比起来还是各有各的好处吧。它们描述各层的能力各有千秋。Verilog HDL善于描述更低层设计,比VHDL更灵活,而VHDL善于描述一些高层的设计(主要是一些算法及控制好实现)。Verilog HDL在仿真方面比VHDL也更方便些,如TESTBEN。
4、FPGA方面需学习的还有很多,为了设计SPI借书查了些资料,才发现自己FPGA基本上还没有入门。电子设计做信号题需加倍努力啊。
正在阅读:
研发会计核算正式文件06-08
云南西双版纳景洪市非开挖定向钻顶管电力管道施工工程08-17
《翻译理论与实践》(笔译)模拟试题09-28
基于单片机的四点温湿度监测系统 - 图文05-20
工程布置及主要建筑物01-16
乔丹励志故事02-17
街道年度工作总结及来年工作计划08-04
有机过渡金属化合物10-06
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 接口
- Verilog
- 语言
- 实现
- 图文
- SPI
- 2015年中药饮片生产流通领域专项整治总结
- 2018年吉安市小升初入学考试模拟考试试题与答案汇总(五份)
- 会展管理综合技能考核(二)实践性考核报告
- 佛山市“三旧”改造专项规划(2009-2020)
- XX钢铁铁路道口无人值守系统技术方案
- 五好家庭事迹材料大集合
- 2016-2021酿酒设备行业发展预测及投资咨询报告(目录) - 图文
- 福建省2012高考语文 第二部分 专题二 第1节 文学名著阅读 红楼梦限时作业
- 江苏省河道堤防巡查办法
- 中国农业银行押品管理办法(试行)
- PeoplesoftHCM项目AE程序技术总结
- 烟草公司七五普法规划
- 呼伦贝尔市委书记曹征海同志在全市上半年经济形势分析会上的讲话
- 《入行论》第33、34课串讲笔记
- 热力学统计物理考试题库选集
- 陈一新讲话汇编
- 2018届河北省衡水中学高三上学期八模考试理综试题-word
- 叉车安全操作规程
- 2015咨询工程师继续教育水电投资政策规划考试题及答案100分
- 2.3 热力学第二定律(高中物理竞赛及高考复习资料)