官方论坛
官方淘宝
官方博客
微信公众号
点击联系吴工 点击联系周老师

2.2 1位闪烁灯设计 -明德扬科教(mdy-edu.com)

发布时间:2021-08-22   作者:admin 浏览量:

本文的文档编号:000800000013

需要看对应的视频,请点击视频编号:000800000162

1、本文章是讲解了如何使用至简设计法来时序1位LED灯间隔1秒,亮N秒(其中N=1 .2. …. 9)的功能


项目背景

    LEDLight Emitting Diode),发光二极管,是一种能够将电能转化为可见光的固态的半导体器件,它可以直接把电转化为光。LED的心脏是一个半导体的晶片,晶片的一端附在一个支架上,一端是负极,另一端连接电源的正极,使整个晶片被环氧树脂封装起来。

半导体晶片由两部分组成,一部分是P型半导体,在它里面空穴占主导地位,另一端是N型半导体,在这边主要是电子。但这两种半导体连接起来的时候,它们之间就形成一个P-N结。当电流通过导线作用于这个晶片的时候,电子就会被推向P区,在P区里电子跟空穴复合,然后就会以光子的形式发出能量,这就是LED灯发光的原理。而光的波长也就是光的颜色,是由形成P-N结的材料决定的。

LED可以直接发出红、黄、蓝、绿、青、橙、紫、白色的光。

最初LED用作仪器仪表的指示光源,后来各种光色的LED在交通信号灯和大面积显示屏中得到了广泛应用,产生了很好的经济效益和社会效益。以12英寸的红色交通信号灯为例,在美国本来是采用长寿命,低光视效能的140瓦白炽灯作为光源,它产生2000流明的白光。经红色滤光片后,光损失90%,只剩下200流明的红光。而在新设计的灯中,Lumileds公司采用了18个红色LED光源,包括电路损失在内,共耗电14瓦,即可产生同样的光效。汽车信号灯也是LED光源应用的重要领域。

对于一般照明而言,人们更需要白色的光源。1998年发白光的LED开发成功。这种LED是将GaN芯片和钇铝石榴石(YAG)封装在一起做成。GaN芯片发蓝光(λp=465nmWd=30nm),高温烧结制成的含Ce3+YAG荧光粉受此蓝光激发后发出黄色光射,峰值550nLEDm。蓝光LED基片安装在碗形反射腔中,覆盖以混有YAG的树脂薄层,约200-500nmLED基片发出的蓝光部分被荧光粉吸收,另一部分蓝光与荧光粉发出的黄光混合,可以得到白光。

对于InGaN/YAG白色LED,通过改变YAG荧光粉的化学组成和调节荧光粉层的厚度,可以获得色温3500-10000K的各色白光。这种通过蓝光LED得到白光的方法,构造简单、成本低廉、技术成熟度高,因此运用最多。

明德扬的教学板一共有8个可发绿光的LED灯。下面是LED灯的原理图。

130 LED原理图

左边的LED1~LED8是板子上LED灯的丝印。右边的LED1~LED8_NET是信号线名,读者在板子上是看不到这些信号线的。

LED灯一端连着高电平3.3V,另一端是信号线LED1~LED8_NET。如果LED1~LED8_NET是高电平,则电流不导通,那么LED灯则不会发光。如果LED1~LED8_NET是低电平,则电流会导通,那么LED灯就发光。所以LED灯发光与否,取决于信号LED1~LED8_NET处于什么电平。

信号线LED1~LED8_NET又连到哪里呢?搜索下原理图文档,可以发现这些信号是连到FPGA的管脚上的。

131

下面信号线和FPGA管脚的连接图,例如信号线LED1是连接到FPGAAA4管脚上。

教学板丝印

信号线

FPGA管脚

LED1

LED1_NET

AA4

LED2

LED2_NET

AB4

LED3

LED3_NET

AA5

LED4

LED4_NET

AB6

LED5

LED5_NET

AA10

LED6

LED6_NET

AB13

LED7

LED7_NET

AB14

LED8

LED8_NET

AB16

LED1~LED8_NET分别与FPGA8个管脚相连,所以LED1~LED8_NET处于什么电平,即LED灯是否要发光,就取决于FPGA管脚的输出了。

例如FPGA管脚AB14连到LED7上。要控制这个灯的亮灭,FPGA只需要将管脚AB14输出为低高就可以了。当输出为高电平时,LED7灯为灭,当输出为低电平时,LED7灯为暗。8LED灯都可由FPGA独立控制。


2 设计目标

本工程使用1LED---LED1,实现一个闪烁灯的功能。工程的工作时钟是50M,也就是时钟周期为20ns。当管脚AA4输出低电平时,LED1灯亮,输出高电平时,LED1灯灭。具体功能要求是:1秒,亮N秒。N的变化是:123---9,然后再次循环。下面是波形图:

132

上板效果图如下图所示。

133


3 设计实现

3.1 顶层信号

新建目录:D:mdy_bookmy_led在该目录中,新建一个名为my_led.v的文件,并用GVIM打开,开始编写代码。

我们先分析一下板子上的LED灯。要控制1LED灯亮和灭,那就FPGA需要产生一个信号,假定为led,这个信号连接到led灯上。要让LED灯灭,FPGA将信号led输出为1;要让LED灯亮,FPGA将信号led输出为0。下面表格表示了硬件电路图的连接关系。

器件

原理图信号

FPGA管脚

FPGA工程信号

LED1

LED1_NET

AA4

led

X1

SYS_CLK

G1

clk

K1

SYS_RST

AB12

rst_n

综上所述,我们这个工程需要三个信号,时钟clk,复位rst_n和输出信号led。将module的名称定义为my_led,为此,代码如下:

1

2

3

4

5

module my_led(

clk    ,

rst_n  ,

led

);

其中clkrst_n是输入信号,led是输出信号,并且三个信号都是1比特的,根据这些信息,我们补充输入输出端口定义。代码如下:

1

2

3

input               clk    ;

input               rst_n  ;

output              led    ;


3.2 信号设计

我们再分析一下功能需求,LED灯的变化规律是暗1秒,亮N秒,其中N的变化是:123---9秒,然后再次循环。从现象转化成信号,其实就是信号led=1持续1秒,然后led=0持续N秒,其中N的变化是:123---9秒。波形示意图如下:

134

上图就是led信号的变化波形图。在第1次时,led=1并持续1秒,然后led=0并持续1秒,共2秒时间;在第2次时,led=1并持续1秒,然后led=0并持续2秒,共3秒时间;以此类推,第9次时,led=1并持续1秒,然后led=0并持续9秒,共10秒时间。然后又再次重复。

由波形图可知,我们需要1个计数器用来计算时间,如2秒、3秒等。本工程的工作时钟是50MHz,即周期为20ns,计数器计数到2_000_000_000/20=100_000_000个,我们就能知道2秒时间到了。以此类推,在第2次时,数到150_000_000个,就知道了3秒时间到。第9次时,数到500_000_000个,就表示10秒时间到。另外,由于该计数器是不停地计数,永远不停止的,可以认为加1条件一直有效,可写成:assign add_cnt==1。综上所述,结合变量法,该计数器的代码如下。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

cnt0<= 0;

end

else if(add_cnt0)begin

if(end_cnt0)

cnt0<= 0;

else

cnt0<= cnt0 + 1;

end

end

assign add_cnt0 = 1 ;

assign end_cnt0 = add_cnt0&& cnt0== x-1;

其中x表示该计数器cnt0要数的个数。该值如何定义,后面再思考。

再次观察波形图,我们发现有第1次,第2次直到第9次的字,说明这还需要另外一个计数器来表示第几次。该计数器表示次数,自然是一次完成了就加1,因为加1条件可为end_cnt0。该计数器一共要数9次。所以代码为:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

always @(posedge clk or negedge rst_n)begin

if(!rst_n)begin

cnt1 <= 0;

end

else if(add_cnt1)begin

if(end_cnt1)

cnt1 <= 0;

else

cnt1 <= cnt1 + 1;

end

end

assign add_cnt1 = end_cnt0;

assign end_cnt1 = add_cnt1 && cnt1==9-1 ;

有了两个计数器,我们来思考输出信号led的变化。概括起来,led有两种变化点:变0和变1。变0的原因都是计数到1秒时间,也就是cnt0数到1_000_000_000/20=50_000_000个时,led0。变1的原因,都是计数时间到了,即end_cnt0。所以led信号的代码如下:

1

2

3

4

5

6

7

8

9

10

11

always  @(posedge clk or negedge rst_n)begin

if(rst_n==1'b0)begin

led <= 1 ;

end

else if(add_cnt0 && cnt0==50_000_000-1)begin

led <= 0 ;

end

else if(end_cnt0)begin

led <= 1 ;

end

end

最后我们再来思考变量x,我们在讨论计数器cnt0的时候,曾经说过“计数器计数到2_000_000_000/20=100_000_000个,我们就能知道2秒时间到了。以类类推,在第2次时,数到150_000_000个,就知道了3秒时间到。第9次时,数到500_000_000个,就表示10秒时间到。”可以看到,cnt0要数多少个是跟第几次有关系的。第1次,数100_000_000个,第2次数150_000_000个。也就是与cnt1有关。因此x的代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

always  @(*)begin

if(cnt1==0)begin

x = 100_000_000 ;

end

else if(cnt1==1)begin

x = 150_000_000 ;

end

else if(cnt1==2)begin

x = 200_000_000 ;

end

else if(cnt1==3)begin

x = 250_000_000 ;

end

else if(cnt1==4)begin

x = 300_000_000 ;

end

else if(cnt1==5)begin

x = 350_000_000 ;

end

else if(cnt1==6)begin

x = 400_000_000 ;

end

else if(cnt1==7)begin

x = 450_000_000 ;

end

else begin

x = 500_000_000 ;

end

end

此次,主体程序已经完成。接下来是将module补充完整。


3.3 信号定义

接下来定义信号类型。

cnt0是用always产生的信号,因此类型为regcnt0计数的最大值为500_000_000,需要用29根线表示,即位宽是29位。

因此代码如下:

1

reg    [28:0]  cnt0  ;

add_cnt0end_cnt0都是用assign方式设计的,因此类型为wire。并且其值是0或者11个线表示即可。因此代码如下:

1

2

wire     add_cnt0  ;

wire     end_cnt0  ;

cnt1是用always产生的信号,因此类型为regcnt1计数的最大值为8,需要用4根线表示,即位宽是4位。因此代码如下:

1

reg    [ 3:0]  cnt1  ;

add_cnt1end_cnt1都是用assign方式设计的,因此类型为wire。并且其值是0或者11根线表示即可。因此代码如下:

1

2

wire     add_cnt1  ;

wire     end_cnt1  ;

led是用always方式设计的,因此类型为reg。并且其值是0或者11根线表示即可。因此代码如下:

1

reg         led     ;

x是用always方式设计的,因此类型为reg。并且其值是最大是500_000_000,需要29根线表示即可。因此代码如下:

1

reg  [28:0]   x       ;

至此,整个代码的设计工作已经完成。下一步是新建工程和上板查看现象。


4 综合与上板

4.1 新建工程

首先在d盘中创建名为“my_led”的工程文件夹,将写的代码命名为“my_led.v,顶层模块名为“my_led”。

135

136

然后打开Quartus Ⅱ,点击File下拉列表中的New Project Wzard...新建工程选项。

137

3.再出现的界面中直接点击Next

138

4.之后出现的是工程文件夹、工程名、顶层模块名设置界面。按照之前的命名进行填写,然后点击Next,在出现的界面再点击next

139

140

5.之后是文件添加界面。添加之前写的“my_led.v”文件,点击右侧的“Add”按钮,之后文件会在下方显示出来,之后点击“Next”。

141

器件型号选择界面。选择Cyclone E,在芯片型号选择处选择EP4CE15F23C8,然后点击“Next”。

142

EDA工具界面。直接点击“Next”。

143

8.之后出现的界面,点击“Finish”。

144


4.2 综合

1.新建工程步骤完成后,就会出现以下界面。选中要编译的文件,点击编译按钮。

145

2.编译成功后会出现一下界面。

146


4.3 配置管脚

147

在菜单栏中,选中Assignments,然后选择Pin Planner,就会弹出配置管脚的窗口。

148

在配置窗口最下方中的location一列,参考下表中最右两列配置好FPGA管脚。

器件

原理图信号

FPGA管脚

FPGA工程信号

LED1

LED1_NET

AA4

led

X1

SYS_CLK

G1

clk

K1

SYS_RST

AB12

rst_n

配置完成后,关闭Pin Planner,软件自动会保存管脚配置信息。


4.4 再次综合

149

在菜单栏中,选中Processing,然后选择Start Compilation,再次对整个工程进行编译和综合。

150

出现上面的界面,就说明编译综合成功。


4.5 连接开发板

图中,下载器接入电脑USB接口,电源接入电源,然后摁下下方蓝色开关。

151


4.6 上板

1.单击以下界面中的

152

2.会出现如下界面,点击add file添加.sof文件,点击“Start”,会在“Progress”出显示进度。

153

3.进度条中提示成功后,即可在开发板上观察到相应的现象。


上一篇:没有了
   拓展阅读