本帖最后由 小墨学FPGA 于 2015-2-1 20:15 编辑
可能是不太适应北京的天气,最近感冒了,鼻子堵得厉害.....外面风很大,也很冷,屋里暖气开的不错,一冷一热之间,这鼻子就得有意见了~ 今天带大家来设计一个自定义的IP核,我们从最基本的做起,包括datasheet 的理解,设计的整体框架,AD转换代码的编写,仿真,Avalon-MM总线接口的编写,硬件系统还是基于上次的硬件系统,不过我们不再用altera给我们提供的IP核了,我们要自己做一个,有时候我们找不到他们提供的IP核,或者有些IP核是收费的,这个时候我们就可以自己来编写自己的IP,虽然没有官方的那么标准,但是用来做一些实验还是没什么问题的。 这次实验我用的是原来我那块板子,因为那块板子上有AD转换芯片,而我们上次搭建的硬件系统是基于cyclone IV的硬件系统,但是这块开发板上没有AD芯片,我们就不做软件下载的实验了,其实只要在我们编写AD转换HDL代码的时候测试成功,那么我们软件调试部分就应该没什么问题了,有条件的同学可以自己做这一部分。
一、有理可依 所有编写的代码必须都得有理可依,要不然直接看代码那得有多痛苦啊,第一部分先来带大家熟悉一下datasheet上的东西 我们要操作的AD转换芯片TLC549的顶层视图
可以看到这个芯片应该不太难操作,左边是模拟信号输入端,因为是模数转换,这边我们就暂时可以不管,看右边有时钟信号,数字信号输出端和片选端,那么我们需要控制的,无非就是时钟信号和片选信号了
还有什么器件描述什么的大家可以自己取去看,我们主要去看时序图
大体上来看一下,,首先是ADC的工作时钟,它在片选信号为低电平的时候有效,连续8个周期用来将转换后的数字信号送到数据总线上,8个时钟周期过后就是转换周期,用来对模拟信号进行转换,在这期间,片选信号要拉高,对于片选信号,开始的时候有一个从高电平到低电平的跳变,然后等待一个建立时间TSU,建立时间结束后ADC工作时钟开始工作,8个时钟周期后,片选拉高开始模数转换,之后片选拉低,将转换后的数据送出去。
细节部分,可以看到当片选拉低后,我们可以定义一个使能信号en来开启工作时钟,从片选拉低到工作时钟有效需要一个建立时间1.4us,这个数据在下面的表格中可以查到,之后是8个数据锁存周期,每一个时钟的高低电平延时不能小于404ns,具体也是表格中找,然后是转换周期,时间是17us,至于转换期间的工作时钟是什么我们可以不必关心。
再来看一下它的注释内容,大体意思是说转换周期需要一个17us的延时,注释B大体意思是说,当片选拉低之后,数据的第8位就自动的放到了数据总线上,剩下的7位数据在第7个时钟下降沿到来的时候就已经锁存了。
二、编程思路
这段时间跟着他们在上课,听李老师讲课的时候,李老师不会将大量的时间放到代码的编写上,而是有时候花一整节课的时间来帮助学生来构建编程的思路,包括系统架构,状态转移图等,有了这些都东西作为铺垫,我们的代码编写就可以手到擒来,起到事半功倍的效果,如果我们不做好事先的准备设计工作,没有一个系统的架构在我们脑海里,上来就去写代码,就会发现越写问题越多,思路不通,处理不当等问题,所以小墨同学回来之后也用word做了这么个状态转移图,这个实验不是很难,状态机也没那么复杂,就是希望起到一个抛砖引玉的过程,通过一个小小的实例,告诉大家以后在拿到一个问题后改怎么下手。虽然画的不怎么样~还是可以看得哈~
理一下编程思路吧,从datasheet里面我们知道。我们要做好这几个延时,即准备转换的延时1.4us,17us的转换延时,和404ns的ADC工作时钟高低电平延时等。状态机部分采用两段式状态机。将组合逻辑与时序逻辑分开,采用独热编码。按照状态转移图构思好状态机的编程思路。数据处理部分,为了保证数据的稳定性,可以采用边沿脉冲检测法检测ADC工作时钟的上升沿,在每一个上升沿将转化后的数据一位一位锁存,由于数据是串行输入,还要用到串并转换的思想,这些编程方法前面都已经介绍过,就不一一讲解了。
代码风格部分,个人感觉这一套代码比起以前有了一些进步,至少看起来思路清晰,注释合理,数据处理恰当,语法直白,没有用到一些很别扭的语法等。具体还需要广大读者自己去体会,也希望你们能够喜欢~
代码部分就不一一讲解了,源代码会附在文章后面,大家可以自行消化
三、仿真与验证
上面是前仿真的过程,从波形来看和我们的设计吻合,用标尺量一下,延时参数也和我们设计的一致
按理说我们下一步需要进行时序约束部分,但是我们的这个设计是us级的,即使不做时序约束也是可以的,但是毕竟我设计的是一个IP核,为了稳定起见还是做一下时序约束比较好。说实话,时序约束部分,个人感觉是一门高大上的学问,变化多端,有些都是经验值,你问一个工程师为什么是这样约束,有时候可能他也答不上来。之前也接触过静态时序分析的知识,但是一直不敢写,感觉还是学的不怎么样吧,想回去以后学内存这方面的时候再去好好研究一下它~
下面是后仿真的波形图
可以看到,波形跟我们的设计吻合,也没有出现什么不合理的设计什么的,可以下板验证了
可以看到,当我们扭动滑动变阻器的时候,相应的模拟量被转化成数字量并在数码管上显示了
四、Avalon-MM总线接口设计
我们知道,我们设计的这个IP核是要挂到Avalon-MM总线上的,作为一个从机,总线需要通过片选信号来访问总线上挂的这些IP,因此,我们也需要给我们的IP设计一个和总线 通信的接口
我们设计AD转换的IP核的片选信号低电平有效,当片选信号有效的时候,如果再来一个读信号,那么,数据就会被总线读走,送至CPU
五、自定义IP
好了,下面我们就可以来定义我们自己的IP了
先将我们刚才设计好的AD转换的.V文件复制到我们硬件系统的目录中,并养成一个好的习惯,新建一个文件夹,并命名为IP,以后我们设计的IP都可以放到里面
打开我们之前硬件系统的sopc builder,双击左上角的NEW component ,在HDL file一栏中添加我们的adc.v文件,
在signal一栏中,根据端口的类型配置端口,时钟复位信号不用说,其中我们的与总线接口部分的端口属于总线的从机端口,我们需要把它定义为avalon_slave_0端口类型,信号类型设置为低电平片选,低电平读就好,其他端口设置为conduit类型,信号类型设置为export,因为我们是用来输出到外部器件的端口
在接口一栏中,我们可以设置一些相关参数,一般为默认就好,为了我们数据的稳定性,我们可以把读延时周期设置为4个,保证它有足够的时间去处理数据
然后点击finish,双击我们生成的IP核将它添加到系统工程中即可,然后重新生成硬件系统
六、硬件系统生成
将生成的新的硬件系统的例化接口声明好,这样在我们的设计顶层又多了这样一个模块,按照惯例分析综合,时序约束,分配管脚,这样我们的硬件系统就设计好了
七、软件部分
因为我的硬件系统上没有AD芯片,这里就只简单说一下软件代码,不做下板调试了
软件部分只讲一下主函数部分,看下图
代码很简单,就是每隔一段时间将采集到的值在窗口打印,不过有个问题需要解释一下,有人会问,我们在自定义IP的时候不是定义了片选端和读信号么,为什么我们没有对它进行操作就可以读数据了呢?
其实我们是不需要对我们的外设进行片选或者读写使能的,因为我们的avalon-MM总线一次只能访问一个从机,我们给出了我们AD转换的IP的地址,就默认片选了这个模块了,又因为我们调用了IO操作的读函数,在定义信号的时候我们定义的是低电平,这样其实就是总线默认帮我们选好了,我们只需要给它一个地址,那么数据就会自动的传到总线上去。
|