FPGA学习之知识体系总结(第二周)

第二周第一天

错题记录:

1.不属于并行语句的是case语句

2.repeat不是分支语句

3.非阻塞赋值运算赋值不是立刻改变

4.三目运算符:?:

5.无锁存器指列举了所有的的情况

6.移位补零

8×8led灯驱动:实现流水灯的话行和列有不同的模值来控制计数,三倍关系,时钟分频,然后状态机,最后组合逻辑电路实现。实现n×nled灯一圈一圈变化的话由于行和列变化频率相同,所以用相同的模值控制。

always语句里面要么全用阻塞赋值,要么全用非阻塞赋值。

遇到的问题:文件名中×(乘号)好像也不能够识别,改了之后综合就成功了。

组合电路中 always块的使用原则

(1)只在一个 always模块中对变量赋值

(2)组合电路采用阻塞赋值

(3)在敏感列表中使用@自动包含所有输入信号

(4)确保包含 if-else和case语句的所有分支

(5)确保所有分支的输出都被赋值;

(6)一种同时满足(4)和(5)原则的方法是在 always块开始时给输出赋默认值;

 

第二周第二天

实现基于FPGA蜂鸣器音乐演奏

蜂鸣器分为无源和有源,有源蜂鸣器频率固定,只有单一音调。FPGA板子和单片机开发板上的蜂鸣器大部分都是无源蜂鸣器,可以由编程实现频率变化,由此发出不同音调的声音。

编程思路:

1.不同的唱名对因不同的分频系数,由此产生不同的音调。要设计分频计数器来记录发出音调的分频系数。

分频系数计算公式:系统时钟频/音频频率/2,除以2代表半个周期,如中音do就是125M/523.3/2.

2.除了音调,还需要节拍,设计一个计时器计数节拍。

3.利用case语句写入节拍和要发出的音调。

实现程序:1.发出中音do  2.依次按下四个button,发出do、ri、mi、fa(这里casex语句比case语句好)  3.谱曲 谱曲就是在第二个程序下增加乐曲中需要的节拍,每秒四个节拍频率要除以4  在每次更新数据时tune_cnt要强制清零,否则tune_cnt与tune_delay可能会越差越大,导致乐曲播放停止。

模块:最后64个状态可以理解为64选1选择器,受beat控制。beat_cnt的模值是系统频率sys_freq的四分之一。Beat在beat_cnt的控制下产生64个beat。每beat产生一次,tune_delay就更新。Tune_delay通过第一个模块产生beep。

 

第二周第三天

上午:连接数码管引脚并测试数码管是否工作正常

下午目标:1.两数码管分别同时显示不同的1和0

2.实现模值可调的加法计数器

3.按键调解计数器可调模值

计数器:计数模块(0-59)→扫描模块(state)→显示译码模块→数码管显像

产生低位:counter%10    产生高位:(counter/10)%10

注意写代码时段选高位到低位依次是:dp-g-f-e-d-c-b-a

显示译码模块(共阳):

reg [7:0]seg;

always@(*)

if(!rst_n)seg=8’hff;

else

case(data_disp)

4’d0:seg=~8’h3f;

4’d1:seg=~8’h06;

4’d2:seg=~8’h5b;

4’d3:seg=~8’h4f;

4’d4:seg=~8’h66;

4’d5:seg=~8’h6d;

4’d6:seg=~8’h7d;

4’d7:seg=~8’h07;

4’d8:seg=~8’h7f;

4’d9:seg=~8’h6f;

4’d10:seg=~8’h77;

4’d11:seg=~8’h7c;

4’d12:seg=~8’h39;

4’d13:seg=~8’h5e;

4’d14:seg=~8’h79;

4’d15:seg=~8’h71;

default:seg=~8’h00;

endcase

 

第二周第四天上午:

改进数码管可变模值计数。注意实例化名字是引用IP核里面的。key_out是模块里面自己定义的btn_out,key_in是btn。

下午:继续改进及呼吸灯的预习

呼吸灯设计原理:呼吸灯设计原理归结为对于分频和占空比的应用,就是先分频,然后再设置占空比的设计。占空比也就是控制LED暗亮的时间达到具有呼吸灯的效果。

脉冲宽度调制(PWM) 的概念:LED的点亮和熄灭,是电平高低变换的结果,可以将一高一低看作一个周期,每个周期一亮一灭,会显示为LED的闪烁,当周期很短,也就是频率很高时,这种闪烁将不被肉眼识别,会让人产生LED连续发光的感觉。在一个周期内,高电平时长与一个周期时长的比叫做占空比,占空比越高,相当于通过LED的电流就越大,视觉上的感觉就越亮。说到这里,应该就有了做呼吸灯的思路,就是改变占空比!让占空比小幅度有级提升,就会有LED无级变亮的感觉。反之就会变暗。占空比越高,亮度越亮。

首先将1s 分为1000份(1ms),然后在1ms内在继续分为1000份(1us),每一个1ms内,依次增加亮灯时间

即:

第1个1ms内亮灯1us

第2个1ms内亮灯2us

第3个1ms内亮灯2us

…… 第1000个1ms内亮灯1000us

 

第二周第五天上午:

计数器的优化  关于消抖的说明:1.IP核调用   2.做一个消抖module再调用(层次化设计) 3.添加一个always块用于消抖

最后讲了一下pwm波

 

第二周第六天:

流水呼吸灯:遇到的问题:给led赋值的时候没有注意到位宽,在写状态机的时候在条件中把state==2’d3写成了state<=2’d3导致一直只有一个状态。

 

学习方法总结:

在编写代码之前,最好像老师一样先把思路理清楚,先打个草稿,清楚自己大概需要哪些模块,没注意到的细节后面来补,先把理论知识了解清楚,这样会比直接想到什么写什么更有效一些。而这些思路是由需求产生的,一般需求就是老师上课所说的要实现的项目目标。设计源代码烧到板子上有错误时,从仿真程序上找错误。然后就是学习能力的逐渐提升,在每犯一个错误的时候就要对这个错误有足够的印象。最后到一定程度了花费在这些错误上的时间就会更少,也提升了熟练度和解决问题的能力。

 

遇到的问题与解决方案

  1. 工程文件名有中文路径和特殊符号都会报错。
  2. 蜂鸣器在谱曲的时候播了一会儿就停止了,在老师讲解下明白是没有强制清零的话tune_cnt与tune_delay会越差越远。
  3. 数码管引脚接错
  4. 按键消抖IP调用实例化明白key_in和key_out表示的意思。
  5. 呼吸灯不呼吸,状态机那里条件语句的条件写错了个。

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注