|
首先要感谢至芯科技能够给我这个学习FPGA难得的机会让我来做第二期的评测,前端时间用CPLD写一个波形发生的程序,也请教过至芯片科技的支老师,支老师的耐心给我留下了深刻的印象,这里要特别感谢一下支老师。另外还要谢谢上海的尤老师。再次谢谢至芯片科技!
非常不好意思,现在才上传我的评测文档,因为大家早就做好了自己的评测并上传到论坛,这里对所有学习FPGA的朋友和网友说声抱歉。
好了,言归正传,开始我们的主题。看过这两期朋友的测评,真心觉得酷!他们对FPGA的掌握程度已经远远超过了我目前的水平,自认为和他们的相比,我所做的东西简直不值得一提!但是既然至芯片科技给了我这个难得的机会相信我能够做好第二期的测评,那么我是不能辜负至芯科技对我的信任和肯定,虽然我能力有限,但是我会拿出我的热情和执着来做好这件事,给至芯科技,给热爱FPGA的朋友一个交代。
看了这么多测评,大家的水平都很高,那么我要给大家说点什么呢?虽然大家的测评文档各种高上大,让我这个FPGA菜鸟无处容身,但是我发现基本上所有的测评文档对细节的考虑欠缺,作为一个菜鸟,我想为那些刚刚入门FPGA或CPLD,或者是停留在入门级别的朋友总结下我自己的学习心得,能够为大家的提高或深入做点贡献,如果我的总结能够为大家带来一点点收获,我就很知足了。
对于ZX-2开发板的硬件资源,第一期有朋友已经总结过了,而且说的非常详细,我就不再这里废话了。我以前学的是CPLD,芯片型号是EPM240T100C5,这个芯片型号的大意是它有100个管脚,属于MAXII家族。
刚入门的朋友可能会问,可编程逻辑器件CPLD或FPGA和单片机之间有什么不同? 他们之间是否可以谁取代谁?
这样说,单片机擅长的领域是工业控制,属于智能控制方面,而对于可编程逻辑器件,它擅长的是数字电路设计,它的编程语言是VerilogHDL语言,它不像C语言,C语言是顺序执行的,而VerilogHDL则是并行执行的,并行执行,意味着执行速度更快,效率更高。
记得学可编程逻辑器件的时候,老师直接教我们写程序,第一个程序就是点亮一个LED,那么要写Verilog程序,有哪些注意呢?什么是一个module?创建一个新的工程需要有哪些注意的地方?等等这些问题相信是入门的朋友遇到的,首先新创建一个工程需要注意的地方,我们的Project名字必须要和第一个module的文件名相同!以后再创建的module名字可以随便命名。另外顶层文件的名字也是可以随便命名的。写一个module的步骤有四个,大家可以看看书,首先说说什么是module?CPLD或FPGA就好比一张白纸,你可以随便在上面画铅笔画,如果你觉得画的不好,还可以重新画,是不是很方便,再或者你还可以把它理解为小孩子玩的积木,积木是一个个零散的部件,他们可以组合成任意一个建筑或形状,这里白纸和积木的共同点就是可重用性,一样的,我们的CPLD或FPGA就是一个可反复修改重用的数字电路,ASIC是专用集成电路,它一旦做好了就不能再修改了,也就是说ASIC的功能是规定的,而可编程逻辑器件或电路可以变换多种多样的数字电路,是不是可以理解了它的意义和奥妙!
说说一个module的四个步骤,首先要有端口的定义,然后要写明输入输出端口,内部变量,最后是过程语句块。一般来说,就这四个内容。
比如可以这样举例:
Module [模块名](输入变量a1,a2,,,输出变量b1,b2…);
输入输出变量
内部变量
过程块
针对always语句块,记住一句话:一个变量只能在一个always语句块里定义,一个always语句只能对一个变量赋值。
点击第一个LED,比如让它以1s的周期闪烁,这时就要分频
下面是分频的程序,不妨记住吧!
always @(posedge clock)
if(En20Hz)
rDivCnt <= 0;
else
rDivCnt <= rDivCnt +1;
always @(posedge clock)
En20Hz <= rDivCnt ==XXX;
当然,rDivCnt这个变量的位宽一定要设置好,不然写好后,有可能因为位宽小而没有实现效果。
如果是数码管的话,数码管的刷屏频率不易过大,因为过大会导致两个数码管的速度一样,尤其是像秒表这样的效果就非常不明显了。
这里在写一般程序的时候需要注意的几个地方:
1、 内部变量的位宽,
比如写数码管程序,要定义位码和段码,如果内部变量的位宽过大,而实际中用到的情况比较少,则很有可能会出错,到时候检查不容易差错,明明程序没有问题,可偏偏就是实现不了预期的效果,很是头疼!
2、 另外always语句块内的条件也是有讲究的,不是乱写的,有的可能是时钟沿,有的可能是一个变量,但不管怎么说,记住一句话,always语句块内的条件的不同会引起程序出错。所以下次程序出错的时候,可能就是你的always内的条件不一样导致的。
3、 在写一个新的程序时,需要在硬件资源里定义好管脚,这里注意要把不用的IO管脚都选择为输入模式,这样是为了保护没有用到的IO管脚不被烧坏。
下面也以一个简单的应用程序来具体说说一些细节,这个应用程序是数字秒表,前面好像有朋友写过了
程序功能:数字秒表
具体实现:可用一个按键来控制秒表的计数、暂停和清零的不同状态
图像显示效果:
顶层文件原理图:
下面结合程序和我的思路来详细说一说
刚才讲到了,新创建第一个工程时,第一个module文件名必须和工程名字一样,这个不要忘记的。我们可以选择分频模块等任意一个模块来做第一个模块。分频模块很简单,这里不再说了
1、 按键模块
下面是ZX-2开发板的按键电路:
这个按键的电路是当没有按键按下时是高,当按下按键后是低,而找完电路原理图也始终没有发现任何一个开发板或处理器的最小系统都具有的东东,大家知道我想说的是什么不?——复位电路!
怎么会没有复位电路?是不是搞错了?这样程序能跑吗?
起初我也是比较纳闷,为什么会没有复位电路这么关键的部分。但直到后来再次浏览这个按键电路部分的时候我豁然开朗。
问一个问题:大家知不知道单片机的复位电路是高电平有效还是低电平有效?
可以这样说,只有51单片机的复位电路是高电平有效,其他任何一款处理器包括STM32、ARM、FPGA、DSP等等都是清一色的低电平有效!
说到这里你是不是明白我下面要说什么了?是的,上面的按键电路不正是我们要寻找的复位电路吗!所以这个问题可以这样来做,我们可以用上面的按键电路来模拟出一个复位电路,不就大功告成了吗。
好了,如何来让一个按键来翻转一个Led,就是按下后led一直是亮的,再次按下后,led就灭了。
程序部分很简单,这里分享一下心得,一般来说,我们会定义一个输入变量,比如KeyIn,输出比如KeyOut,把KeyIn赋值给KeyOut,这是定义按键,还不能实现翻转,需要再定义个内部变量,rTemp,程序这样写:
always @(posedge Clock)
rTemp1 <= KeyIn;
always @(posedge Clock)
KeyOut <= KeyIn & !rTemp1;
这样就可以实现用一个按键来翻转LED了,当然这个LED可以是其他的外设等等。但这样仍然会问题——按键机械抖动。那么如何去除抖动呢?这个方法很多,这里不再一一赘述。有上下沿判断法,有延时方法、还有设变量存储记忆等方法。
2、显示模块
图片如下:
写这个模块的时候我废了一些时间,因为这个和我以前写的有点不一样,我以前用的板子,数码管的位码和段码是直接连接到芯片的管脚上去的,所以在用的时候很方便,直接定义就可以驱动了,但这样做的唯一不好的地方就是浪费芯片的IO资源!在芯片寸土寸金的IO资源上能尽可能少占IO就少占,所以ZX-2开发板上的数码管的位码是用了一个74HC138的译码器来片选的,这里再写位码的时候就需要好好考虑下了
首先,需要定义一个变量 reg [1:0] DBit ;
还要定义一个计数变量 reg rBitCnt;
可以这样写:
Always @(posedge Clock or negedge nReset)
Case(rBitCnt)
0: DBit <= 3’b000;
1 Bit <= 3’b001;
3、计数模块
图片如下:
这里用到了状态机这一思想,需要注意的计数开始时,先计数个位,当个位满9后就向十位进位。这个部分的程序还是比较简单的,程序略。
至芯科技ZX-2开发板测评的第一份文档我先写到这里,内容比较简陋,开发的好的程序也不是很多很优秀,在接下来还有时间的话,我会继续上传我的学习内容,和活动没有关系,只因为一份热爱。
再次感谢至芯科技能够给我这个学习FPGA的好机会,感谢支老师,感谢尤老师!
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?我要注册
x
|