1. 实验要求及目的:
接着上次的实验,但是这次需要使8个LED周期性的闪烁。这次我就不详细的贴图说明每个步骤了,如果和上一个实验有不同的,需要特别说明的,我才贴图。
使用软件:Quartus II 5.0。
2. 硬件原理图:
这个是我自己制作的开发板上的LED的原理图,一共有8个,IO和别的共用的,使用八个LED的时候板上的JP1和JP5全部戴上短接帽,JP2则空出。如果要点亮这些LED,只需要把与其相连接的FPGA管脚输出低电平“0”就可以实现这个功能了。(我焊板子的时候把LED1弄坏了,不能用。)
LED管脚对应的情况如下:
D1------PIN_97
D2------PIN_94
D3------PIN_91
D4------PIN_84
D5------PIN_82
D6------PIN_78
D7------PIN_76
D8------PIN_74
另外,本实验需要用到时钟计数,时钟对应的引脚为PIN_16。
本文均采用输出“0”点亮的模式,以下就不再另外再说明了。
——这几句话我直接抄袭上一个实验的了,因为是一样的。
3. 程序设计
(1)设计分析:我们要求这次8个灯周期性的闪烁,什么意思呢?简单点说,就是那八个灯一会儿亮一会儿灭,如何实现呢?
我们通过上一个实验知道了,按照我给出的原理图,只要把与LED相连的FPGA管脚置低,也就是输出低电平“0”,就可以实现点亮LED的功能。反之,通过输出高电平“1”,我们就可以实现熄灭LED了。
周期性的闪烁,就是要使FPGA的IO周期性的输出“0”和“1”。讲的够明白了吧:)
这个周期是怎么来的呢?比如说我们需要让LED亮0.5s灭0.5s,那么这个周期就是1Hz。我板子上使用的晶振是50MHz,也就是1Hz的50000000倍。(有点罗嗦了,汗!)那么我们就利用计数器计数。等计到50000000/2的时候,把输出状态求反,那么亮着的灯就变灭了,灭的灯也就变亮了。
废话少说,来看看源程序吧。
(2)源程序 exp2.v
程序代码:
// Light 8 LED periodically
// Designed By Smokingfish @ www.51FPGA.com zhiyuh@163.com
module exp2(LED,CLK);
output[7:0] LED;
input CLK;
reg [7:0] LED;
reg [24:0] counter;
always@(posedge CLK) //在时钟负延跳变,也就是计数什么的
begin
counter<=counter+1; //计数器加1
if(counter==25'b1_0111_1101_0111_1000_0100_0000) //这个数就是25000000
begin
LED<=~LED; //求反,闪烁
counter<=0; //重新计数
end
end
endmodule
4. 实验步骤
(1)打开Quartus II软件,进入集成开发环境,点击File->New project wizard..新建工程项目exp2,直接点击Finish。
(2)点击File->New..在该项目下新建Verilog HDL源程序文件exp2.v,输入上面的源程序代码并保存。
(3)选择所用的FPGA器件----EP1C3T144C8,以及进行一些配置。
选择配置器件,如果要下载程序到EPCS1的话。
选择不需要使用的IO功能。选择As inputs,tri-stated。
点击两次ok,回到主界面。
(4)为工程项目锁定引脚:
点击Assignments->Pins,配置LED[0]---LED[7]以及CLK的引脚。
(5)编译工程项目:点击Processing->Start Compilation。
(6)仿真:这个实验我简单的讲一下利用QuartusII的VWF文件进行仿真的流程。(我自己懒的很,所以就抄了点书,呵呵)
1)打开波形编辑器。选择File->New,在New窗口的Other Files中选择Vector Waveform File(如下图):
2)设置仿真时间区域。点击Edit->End Time..,出现下面的对话框,设置正割仿真域的时间:50us。为什么选这么小呢?当然有原因的,太长了机器要跑好长时间,自己会很难受的,呵呵。但是计数器要计数那么多次才行,50us估计还没有到一次求反就结束了,怎么办呢?那么我们把计数减小一点,把25000000这个数变成25,也就是把源程序中的12行的那个数改成1_1001。(记得保存哦,还有就是要重新编译一下工程)
3)保存波形文件:这个不用我说吧?默认的名字是你的工程的名字。
4)将工程中的端口信号选如波形编辑器中。
首先选择View->Utility Windows->Node Finder。弹出下面的对话框。
在Filter这个选项框里面选择:Pins:all,点击List按钮,下面就会出现工程中所有端口的引脚名。然后就可以看到这样的效果了:
用鼠标把CLK和LED信号分别拖拽到波形编译窗口。注意,是拖到红色那个框里面,不要拖到右边白色的框了——那样是拖不进去的。
关闭这个对话框,进入波形编辑。选择上图红色部分里面的CLK信号,使其编程蓝色条(编辑状态)。然后单击左侧的时钟设置键(下图红色的那个),然后出现蓝的部分的对话框(没有点之前是没有的,注意哦)。然后设置时钟周期为10ns,占空比为50%。
设置总线数据格式:单击LED这个信号旁边的“+”,就可以展开这个总线中的所有信号。如果双击LED信号,就可以看到下面这个对话框,在Radix里面有四个选项,可以选择显示数据的模式,我这里选择的是无符号十进制整数(Unsigned Decimal)。
对仿真器进行一些设置:选择Assignment->Settings..,出现下面的对话框,选中Category里面的Simulator,,则出现右边的设置。在Simulation mode中选中Timing(时序仿真)——蓝色部分,Simulation input(仿真激励文件)选中exp2.vwf——黄色部分,点里面的蓝色部分可以选择文件;并且选中Simulation coverage reporting以及Glitch detection(毛刺检测),宽度为1ns。其实这样的仿真并不是很严格,因为我们修改了时钟频率,但是这里我主要是为了简单的讲解一下怎么仿真,所以就这么设置了,你可以根据你的具体时钟周期选择这些数值(包括仿真域的以及时钟周期还有就是这里的毛刺检测宽度)。完成之后点击ok。
下面就可以启动仿真器进行仿真了。点Processing->Start Simulation,直到出现Simulation was successful,仿真结束。
观察仿真结果。仿真的波形文件“Simulation Report”自动弹出(注意,Quartus II的仿真波形文件中,波形编辑文件(*.vwf)和波形仿真报告文件(Simulation Report)是分开的,这个和Maxplus II是一个很大的不同点。)用放大缩小按钮(这个我就不贴图了,自己在左侧的快捷图标里面找一下,第二排第二个,就是那个放大镜的图标。左键放大,右键缩小,也可以在报告文件里面点右键选Zoom来放大缩小),使报告的波形能比较清楚的显示。如下图:
基本能看到了,八个LED出现了周期性的01变化。但是不能根据我们的计数器来判断是不是计数到了0.5s的时候跳变的啊,这是为什么呢?因为我们在编辑仿真波形的时候并没有把counter这个变量加进去,只是加入了输入输出引脚。
那我们重新回到波形编辑器窗口,这次我们不使用View->Utility Windows->Node Finder这个办法,我教你另外一个办法:我们双击第六个图的红色部分的空白处,会出现这样的对话框:
现在你可以直接在Name里面输入我们需要观测的计数寄存器信号名:counter。Radix选择无符号十进制整数。当然如果不想动键盘,完全可以用鼠标全部操作,那就是点Node Finder..,这就出现了前面所用的那个窗口,其实道理是一样。不过如果你没有改变设置,这次怎么你也找不到counter这个信号,为什么呢?很简单,因为Filter里面我们选择的是Pins:all,也就是FPGA管脚,而counter是我们程序内部的计数寄存器,没有输出也没有输入。这次我们在Filter里面选择Design Entry(all names),然后点List,就可以在左边的窗口里面找到counter这个寄存器了。这次就不能用拖拽的办法把它拖到波形编辑器了,于是我们双击counter,它就跑到右边的窗口了(见下图),然后点两次ok,回到波形编辑器主界面。
这下就可以观察根据counter的计数LED的变化情况了。当然你要首先保存文件,然后重新仿真,结果如下图:
如果放大缩小还不能比较清楚的看波形,可以点全屏的按钮(左侧工具的第三排那个——第三排只有一个)。我们仔细研究一下这个仿真结果,发现了问题了吗?
如果你是细心的人就会发现,我们计数是从0开始的,然后加到25之后的一个始终周期LED才开始跳变,所以其实我们多了一个时钟周期的计数。如果是25Hz的时钟,那么多计数一个周期就是0.04s,50MHz的话就是0.04ns,误差虽然不大但是我们编程也要严谨才行。所以返回源程序修改counter的值为11000,然后重新编译和仿真,直到结果完全符合我们的要求。
这里有一个问题,如果你关闭了仿真报告文件的窗口第二次仿真结束之后有时候就不会自动弹出仿真报告文件的窗口,可以通过点击Processing->Simulation Report来打开。
最后把counter的数值改成50MHz晶振的数值,这个不要忘记了,要不然板子上的LED变化的很快,我们肉眼基本看不到有什么闪烁。值为最初给出的代码里面的值-1,也就是1_0111_1101_0111_1000_0011_1111(十进制的24999999),然后编译工程。
(7)下载目标文件到板子上: 点击Tools->Programmer,选中Jtag模式,并且选中目标文件,然后点Start。
终于完成了第二个实验,这下可以看到板子上的8个LED间隔点亮,间隔0.5s的时候变化一次(亮的变暗,暗的变量)——效果可以看下面的这个Flash文件。是不是觉得比上个实验更有意思呢?通过这个实验我们又学到了什么呢?仿真,还有就是计数器的使用,有没有一点点收获呢?希望能有一点,要不我的这个教程不是白写了么?