2. 流水灯小计

流水灯里面注意的问题



在学习单片机时我们刚开始都是通过点亮一个LED灯来给我们自己一个真实的直观的认识,因此在建立的第一个FPGA工程的时候,我们也使用了一个点亮LED的范例,这里我们将讨论在FPGA中如何实现点亮LED这一话题。 
1、程序编写 
  一般FPGA的核心电平是1.2V,管脚电平是3.3V,所以,要想点亮哪个LED,只要给连接的那个管脚赋0,不点亮赋1就可以了(注意此处对管脚赋0或1取决于硬件电路的设计,一般来讲如果LED的负极挂接在FPGA的IO口上时则赋0点亮,反之赋1点亮)。 
点亮四个LED的程序我们是这样写的:

 1 module led (
 2 clk,rst_n,
 3 led
 4 );
 5
 6 input clk;
 7 input rst_n;
 8 output[3:0] led;
 9 reg[3:0] led_r;
10
11 always @(posedge clk , negedge rst_n)
12 begin
13 if(!rst_n)
14 led_r <= 4‘b1111;
15 else
16 led_r <= 4‘b0; // led是一端接上拉电阻,输入低电平点亮
17 end
18 assign led = led_r;
19 endmodule 

2、程序简介 
  这里我就讲点Verilog的经验之谈,有不妥的地方还请大家多指正。关于Verilog语法,还请大家找本书系统地学习下,这里无法一点一点细讲,要细讲的话书上是最合适的。推荐两本书,一本是夏宇闻老师的《Verilog 数字系统设计教程》 ,另外一本《设计与验证Verilog HDL》也很不错。 
Verilog的一个程序模块,是以module 和 endmodule 开头和结尾的。跟在module后面的是这个模块的模块名。模块名后面的括号里列出了这个模块的输入输出管脚列表。再接下来我们要对这些管脚是输入input 还是输出 output 以及是多少位进行描述。再接下来差不多就是程序的正文了。 
我们知道,数字电路就分为两种:组合逻辑电路和时序逻辑电路。其实我们写的FPGA程序它不叫程序,它一般叫做硬件描述语言,(这里我也是图方便混着叫了,嘿嘿)。说这个呢,想表达这么个意思:我们写了FPGA程序,然后Quartus/ISE帮我们综合到FPGA芯片中,在FPGA内部就是生成两种数字电路,组合逻辑电路和时序逻辑电路。 
  所以,我们写程序,也就两种逻辑电路的描述。凡是clock信号有关系的就是时序逻辑,跟clock没什么关系的就是组合逻辑(这是我妄自断言,还没有出处,有问题的话请拍砖)。这就引出了wire数据型和reg数据型的问题,还有阻塞赋值和非阻塞赋值。这些概念大家一定要在书里仔细阅读。 
学习Verilog并不难,花个一天时间看下书,弄个程序写一下基本就会了。对于以前一直从事c语言,c++软件开发的同学,首先得理解这样的问题。我们所写的Verilog程序,并非软件程序,它是用来描述硬件电路的代码: 
3、 换个玩法 
  四个LED亮着是不是没什么好玩的呢?我们可不可以这样的,让四个灯轮流亮起来,就是第一个灯亮了之后熄灭,然后第二个亮再熄灭,接着第三个,第四个。这个流水灯,或者叫跑马灯,大家在做单片机实验的时候估计都做过吧。这里我们只要做一个移位寄存器就可以了。我们修改下面这段程序

1 reg[3:0] led_r;
2 always @(posedge clk,negedge rst_n)
3 begin
4 if(!rst_n)
5 led_r <= 4‘b0111;
6 else
7 led_r <= {led_r[0],led_r[3:1]};
8 end 

{}是Verilog里的拼接运算符,这句{led_r[0],led_r[3:1]}的意思就是把上次led_r的第0位移到最高位,然后高3位往右移。也就是说,最初,我们给四个led的赋值是0111,那只有最高位的那个led灯是点亮的。第一次移位后变成1011,那就只有第二个是亮的;接着1101,第三个;1110,第四个;然后又变成第一个0111。

4、点灯进阶 
  按原理分析,我们应该是实现了流水灯这个功能了。下载到板子上看看效果吧。结果估计另大家都失望了,怎么回事?四个LED灯都还亮着。聪明的同学估计找到原因了,但我还想买个关子,我们先做下面的实验。

 1 module led (
 2 clk,rst_n,
 3 led
 4 );
 5
 6 input clk;
 7 input rst_n;
 8 output[3:0] led;
 9 reg[19:0] cnt;
10
11 always @(posedge clk , negedge rst_n)
12 begin
13 if(!rst_n)
14 cnt <= 20‘b0;
15 else
16 cnt <= cnt + 1‘b1;
17 end
18 reg enable_r;
19 always @(posedge clk , negedge rst_n)
20 begin
21 if(!rst_n)
22 enable_r <= 1‘b0;
23 else if (cnt == 20‘hfffff)
24 enable_r <= 1‘b1;
25 else
26 enable_r <= 1‘b0;
27 end
28
29 wire enable;
30 assign enable = enable_r;
31
32 reg[3:0] led_r;
33 always @(posedge clk , negedge rst_n)
34 begin
35 if(!rst_n)
36 led_r <= 4‘b1;
37 else if(enable)
38 led_r <= {led_r[0],led_r[3:1]};
39 else ;
40 end
41
42 wire[3:0] led;
43 assign led = led_r;
44 endmodule 

我又写了上面这段程序,程序中我增加了一个计数器cnt。开始,计数器是20位的,每个系统时钟的上升沿 posedge clk 执行一次计数器 +1 操作 cnt <= cnt + 1‘b1 。 在计数器计数到满的时候,我定义了一个enable信号 else if (cnt == 20‘hfffff) enable_r <= 1‘b1;而其他时候,我都让这个 enable 信号维持低电平。(这里加一句,计数器到满的时候 cnt = 20‘hfffff再 + 1 它就溢出了,回到20’h0)。

1 reg[3:0] led_r;
2 always @(posedge clk or negedge rst_n)
3 begin
4 if(!rst_n)
5 led_r <= 4‘b1;
6 else if(enable)
7 led_r <= {led_r[0],led_r[3:1]};
8 else ;
9 end 

然后我们再看这段程序,我让它只有在 enable == 1’b1 的时候进行移位。大家把这段程序下载到板子上,有什么现象?四个led在闪动。 
5、答疑解惑 
  好了,这个关子就卖到这里了。问题出在我们的眼睛骗了我们。百度一下,知道一个数据:人眼分辨事物的最高频率为24HZ,即反应一次要0.042s 。我们最初的移位是用的系统时钟clk,它是50MHZ,也就是说灯的每盏灯的亮灭是按50M的速度在移动,眼睛当然是完全看不出来啦,所以效果跟四个灯全亮是一样的。 
后面我们用了一个计数器,使移位变成了2的20次方个CLK时间,即频率变成了50M/1048576 ,约等于50 HZ,这时我们的眼睛还是分辨不了,所以我们看到四个灯都在闪烁。 
  接下来,我们再把计数增大一点,把移位的频率降下来,就能看到流水灯的现象了。 
这是个有趣的现象,相同原理的实验我在本科的时候做过,那时候也没太在意。最近发现安装在山地车轮胎上的“风火轮”也是用的这个原理哦! 
6、总结 
  这一篇我们讲了LED点亮的原理,以及计数器的设计,还有流水灯的设计。好玩吧!有兴趣的欢迎加入一起学习!

时间: 2024-10-04 22:58:40

2. 流水灯小计的相关文章

简易项目(1)流水灯项目讲解

写在前面的话 这一节呢,我们来实现一个流水灯驱动程序的编写,当然啦,点灯不是目的,最重要的是我们通过这个流水灯代码的实现可以掌握一些重要的规范. 项目需求 我们要求流水灯模式如下:当复位键按下时,灯全部熄灭,当复位键放开以后,首先,点亮第一个灯,然后第一个灯熄灭,同时点亮第二个灯,接着,第二个灯熄灭,同时点亮第三个灯,然后,第三个灯熄灭,同时点亮第四个灯,最后第四个灯熄灭,同时点亮第一个灯,如此循环往复,实现流水. 相关技术介绍 项目需求,我相信大家已经看清楚了,那么,接下来我们该怎么做呢?写代

【黑金原创教程】【FPGA那些事儿-驱动篇I 】【实验一】流水灯模块

实验一:流水灯模块 对于发展商而言,动土仪式无疑是最重要的任务.为此,流水灯实验作为低级建模II的动土仪式再适合不过了.废话少说,我们还是开始实验吧. 图1.1 实验一建模图. 如图1.1 所示,实验一有名为 led_funcmod的功能模块.如果无视环境信号(时钟信号还有复位信号),该功能模块只有一组输出端,亦即4位LED信号.接下来让我们来看具体内容: led_funcmod.v 1. module led_funcmod2. (3. input CLOCK, RESET,4. output

第一个FPGA工程—LED流水灯

这一章我们来实现第一个FPGA工程-LED流水灯.我们将通过流水灯例程向大家介绍一次完整的FPGA开发流程,从新建工程,代码设计,综合实现,管脚约束,下载FPGA程序.掌握本章内容,大家就算正式的开始入门FPGA开发了. 1.1.1.电路说明 1.1.2.新建工程 第一步:从开始菜单启动Quartus II 13.1(64 bit) ,如下图. 第二步:菜单栏选择File->New Project Wizard,新建工程. 第三步:弹出新建工程对话框,点击Next,下一步. 第三步:如下图,依次

[Google Map]使用小计

这里是基于API3基础上,关键代码: var allMarkers = []; var map = null; var mgr = null; var infoWindow; function setupMap(xlat, ylng, zoom, gdiv) { var Options = { zoom: zoom, center: new google.maps.LatLng(xlat, ylng), mapTypeControl: false, //地图卫星控件不显示 mapTypeId:

单片机教程4.C语言基础以及流水灯的实现

单片机教程4.C语言基础以及流水灯的实现 C语言,没接触过计算机编程语言的人会把它看的很神秘,感觉非常的难,而在我看来,C语言的逻辑和运算,就是小学水平,所以大家不要怕它,我尽可能的从小学数学逻辑方式带着大家学习C语言. 1.1 二进制.十进制和十六进制 看似很简单的东西,但是从同学们学习视频的情况来看,很多同学不能彻底明白.这里先简单介绍一些注意事项,然后还是从实验中讲解会比较深刻. 1.十进制就不多说了,逢十进位,一个位有十个值:0-9,我们的生活中到处都是它的身影.二进制就是逢二进位,它的

STM32f103之流水灯

       这几天打算复习下stm32有关的硬件资源,就想着从最开始做起,熟悉下当初所学的知识.学习stm32最初都基本是从流水灯开始的,今天就开始点亮流水灯.        首先,必须明白流水灯的硬件原理,以下是原理图: 它由8个管脚控制,因此首先必须进行初始化8个引脚. //初始化PE8...PE15为输出口.并使能这八个口的时钟 //LED IO初始化 void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2P

FPGA流水灯实验

源代码下载地址: http://pan.baidu.com/s/14H8D4 FPGA流水灯实验 花了几天通过流水灯实验把学习的verilogHDL的建模技巧总结了一下.写一份总结,给自己制定一套规范,方便以后查看和解决问题. 实现目标: 通过流水灯的实验实现了串行工作,流水线工作(时间并行),并行流水线工作(空间并行).串行工作是CPU的工作方式,也就是一个时间只能做一件事.通过verilogHDL完全可以模仿这种工作方式,也就是说通过CPU实现的算法和驱动程序完全可以转换成对应的verilo

[BaiDu Map]使用小计

最近从谷歌地图转移到百度地图,关于其中操作代码备记下,其中包括关于MarkerManager使用,代码基于API 2.0: var allMarkers = []; var map = null; var mgr = null; var infoWindow; /* baidumap初始化 *xlat,ylng 经纬度 *zoom 缩放级别 *gdiv 承载div */ function setupMap(xlat, ylng, zoom, gdiv) { map = new BMap.Map(

20180805 玩玩FPGA开发,学学Verilog,学学基本操作,制作流水灯

20180805 玩玩FPGA开发,学学Verilog,学学基本操作,制作流水灯 我毕业设计做的就是FPGA,但是什么都没有学.校外毕设老师对我非常无奈,不过还好,校内的指导老师送了我一个很久很久的开发板,配套的教程是2010年的竞赛教程,教程里的截图很显然的win7风格--下面是老师送的开发板上的照片,能玩的地方有:小灯和数码管,还有一个VGA的输出接口.(家里没有VGA线,懒得买,所以就不玩这个了) 图:老师送的板子和下载线 一.开发环境搭建 这点没什么可说的,就是下载一个ISE14.7(板