【FPGA实战篇三】 状态机实现按键控灯
状态机实现按键控灯)
一、状态机
1、状态机认识
有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
- 状态存储关于过去的信息,就是说:它反映从系统开始到现在时刻的输入变化。转移指示状态变更,并且用必须满足确使转移发生的条件来描述它。动作是在给定时刻要进行的活动的描述。
- 有多种类型的动作:
- 进入动作(entry action):在进入状态时进行退出动作:
- 在退出状态时进行输入动作:
- 依赖于当前状态和输入条件进行转移动作:在进行特定转移时进行
FSM(有限状态机)可以使用上面图1那样的状态图(或状态转移图)来表示。此外可以使用多种类型的状态转移表。下面展示最常见的表示:当前状态(B)和条件(Y)的组合指示出下一个状态(C)。完整的动作信息可以只使用脚注来增加。包括完整动作信息的FSM定义可以使用状态表。
状态转移表
2、状态机分类
Moore机
只使用进入动作的FSM,就是说输出只依赖于状态。Moore模型的好处是行为的简单性。
Mealy机
只使用输入动作的FSM,就是说输出依赖于输入和状态。Mealy FSM的使用经常导致状态数目的简约。
3、相关资料参考
二、按键点灯
1、功能描述
通过按键key控制led灯的状态。
2、功能实现
按键状态 | LED显示状态 |
---|---|
无按键按下 | 四个LED灯全灭 |
按下key0 | 自右向左的流水灯 |
按下key1 | 自左向右的流水灯 |
按下key2 | 四个LED灯同时闪烁 |
按下key3 | 四个LED灯全亮 |
3、系统框图
三、创建工程
有关quartus相关的工程创建方法,可以参考博客:
1、VScode创建工程项目
创建文件夹,命名为工程名称
在此文件夹中,再次创建三个文件夹(prj、sim(tb)、src(rtb))
在src文件夹内创建文本文档(鼠标右键→新建文本文档)
更改名称为项目模块名(点击确认更改扩展名)
打开VScode
找到你所创建的文件路径,添加进去
可以看到添加的文件
单击src,选择创建的文本,编写项目源码(这里是已经完成的项目)
源码编写完成后,打开quartus,选择创建新工程
编辑项目信息
添加文件到项目
选择型号以及芯片【EP4CE6F17C8】
选择仿真版本(根据自己安装进行选择)
创建完成,信息对照
2、项目编译
编译
编译结果
3、查看逻辑电路图
图示
电路原理图
4、引脚配置
相关元件对应引脚
元件 | 引脚 |
---|---|
LED0 | G15 |
LED1 | F16 |
LED2 | F15 |
LED3 | D16 |
key0 | E15 |
key1 | E16 |
key2 | M16 |
key3 | M15 |
clk | E1 |
点击图标配置引脚
配置完成图示
更改引脚value
①
②
③
更改后,点击OK,再点击全编译
5、项目源码
module key_led (
input clk, //50M时钟
input rst_n,
input wire [3:0] key, //按键
output reg [3:0] led //led灯
);
//0.2s计数器,10_000_000次,24位宽
reg [23:0] cnt;
//定义状态计数器,4个状态,2个位宽
reg [1:0] flag;
//计数器模块
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt <= 24'b0;
else if(cnt == 24'd10_000_000 -1)
cnt <= 24'b0;
else
cnt <= cnt + 1'b1;
end
//根据0.2s计数器切换状态
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
flag <= 2'b0;
else if(cnt == 24'd10_000_000 -1)
flag <= flag + 1'b1;
else
flag <= flag;
end
//根据按键控制不同状态下的led
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
led <= 4'b0000;
else if (!key[0] ) begin //按下key0键,自右向左流水灯
case (flag)
2'd1 : led <= 4'b0001;
2'd2 : led <= 4'b0010;
2'd3 : led <= 4'b0100;
2'd4 : led <= 4'b1000;
default : led <= 4'b0000;
endcase
end
else if (!key[1]) begin //按下key1键,自左向右流水灯
case (flag)
2'd1 : led <= 4'b1000;
2'd2 : led <= 4'b0100;
2'd3 : led <= 4'b0010;
2'd4 : led <= 4'b0001;
default : led <= 4'b0000;
endcase
end
else if (!key[2] ) begin //按下key2键,闪烁
case (flag)
2'd1 : led <= 4'b1111;
2'd2 : led <= 4'b0000;
2'd3 : led <= 4'b1111;
2'd4 : led <= 4'b0000;
default : led <= 4'b0000;
endcase
end
else if (!key[3]) //按下key3键,全亮
led <= 4'b1111;
else
led <= 4'b0000;
end
endmodule
四、开发板验证
1、程序烧录
连接开发板,打开电源
点击图标,烧录程序
程序烧录
点击start,烧录成功
2、功能验证
①无按键按下
②按下key0
③按下key1
④按下key2
⑤按下key3