| **银杏科技有限公司旗下技术文档发布平台** ||||
|技术支持电话|**0379-69926675-801**|||
|技术支持邮件|Gingko@vip.163.com|||
^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^
| V1.0 | 2020-11-25 | zgf | 初次建立 |
===== 实验十二:有限状态机实验——一段式状态机描述 =====
==== 一、 实验目的与意义 ====
- 掌握一段式状态机的描述方法。
- 掌握宏定义、参数变量的使用方法。
==== 二、 实验设备及平台 ====
- iCore3L 双核心板。
- XiST USB-CABLE(或相同功能)仿真器。
- Micro USB线缆。
- 装有HqFpga开发软件的电脑一台。
==== 三、 实验原理 ====
* 有限状态机(Finite-state machine,FSM),简称状态机,是一种表示有限个状态及在这些状态之间的转移和动作等行为的数学模型。
* FSM通常由组合逻辑和寄存器两部分组成。寄存器用于存储状态,组合逻辑完成状态译码和产生输出信号。状态机的组成有3各基本要素:状态、输入和输出。其中状态是用来划分逻辑顺序和时序规律的变量;输入指的是状态机进入每个状态的条件;输出指的是在某种状态下发生的事件。
* 描述状态机关键要描述清楚状态机的三个要素,即如何进行状态转移、每个状态的输出是什么、状态转移的条件是什么。状态机有3种常用的描述方法:一段式、二段式和三段式。根据输出与输入的关系,又可以分为两大类:
* 若输出只和状态有关而与输入无关,则称为Moore型状态机;
* 若输入不仅和状态有关而且和输入有关系,称为Mealy型状态机。
* 一段式描述方法是将状态转移的组合逻辑和状态寄存器转移的时序逻辑写在一个always模块中。缺点是不符合Verilog将时序逻辑和组合逻辑分开描述的代码风格,且整个代码结构不够清晰,不利于代码维护和升级,也不利于附加约束、设计的综合和布局布线。
* 结合本实验的工程代码,理解一段式状态机的描述方法及其局限性。
==== 四、 代码讲解 ====
* 本实验以控制LED闪烁为目的,演示一段式状态机的代码格式,便于加深对一段式状态机写法的理解。
* 功能上,通过状态切换实现led的闪烁,根据功能描述,可以知道,LED闪烁功能状态包括LED亮状态和LED灭状态,以及状态转移判断条件(state_sig=1?)。
* 在state_idle状态,LED显示1秒蓝色,便于状态转移的观察;1秒后,状态转移信号有效,状态机跳转到state_led_on状态,点亮LED;再过1秒,状态转移信号有效,状态机跳转到state_led_off状态,关断LED;当标志信号再次到来,状态转移信号有效,状态机又跳转到state_led_on状态,点亮LED;如此循环实现led闪烁功能。根据这些信息可以画出状态转移图如下:
{{ :icore3l:icore_fpga_12_1.png?direct |图 12-1 状态转移示意图}}
* 状态转移信号state_sig是通过对25Mhz的系统时钟信号进行计数实现的。以系统时钟上升沿作为触发信号进行计数。计数满25M时,则计数时间持续1秒钟,跳转控制信号拉高1个时钟周期。代码如下:
//------------------------------------------------//
//time_cnt循环计数,周期约1秒(因为从0计数到25000000,实际上是25000001个时钟周期)
reg [31:0] time_cnt;
always@(posedge fpga_clk or negedge rst_n)
if(!rst_n)
time_cnt <= 32'd0;
else if(time_cnt==32'd25000000) //以25MHz系统时钟计数,计时约1秒
time_cnt <= 32'd0;
else
time_cnt <= time_cnt + 1'd1;
//------------------------------------------------//
//拉高1个系统时钟周期的标志信号state_sig。
reg state_sig;
always@(posedge fpga_clk or negedge rst_n)
if(!rst_n)
state_sig <= 1'b0;
else if(time_cnt==32'd25000000)
state_sig <= 1'b1;
else
state_sig <= 1'b0;
//------------------------------------------------//
接下来看一下代码的主体。状态机的状态转移和不同状态下的逻辑功能实现,代码如下:
//------------------------------------------------//
//定义LED状态常量寄存器
parameter LED_OFF = 3'b111;
parameter LED_ON = 3'b000;
//------------------------------------------------//
reg [2:0] led;
reg [2:0] led_state;
always@(posedge fpga_clk or negedge rst_n)
if(!rst_n)
begin
led <= 3'b111; //复位状态,三色LED为灭状态。
led_state <= `state_idle;
end
else
case(led_state)
`state_idle:begin
led <= 3'b110; //idle状态三色LED显示蓝色。
if(state_sig) //检测到计时1秒标志信号,进入LED亮状态。
led_state <= `state_led_on;
//此时只是状态的转移,LED状态还未改变。
else
led_state <= led_state;
end
`state_led_on:begin
led <= LED_ON; //进入LED亮状态后点亮三色LED.
if(state_sig)
led_state <= `state_led_off;
else
led_state <= led_state;
end
`state_led_off:begin
led <= LED_OFF; //关断LED。
if(state_sig)
led_state <= `state_led_on;
else
led_state <= led_state;
end
endcase
assign fpga_led = led;
//------------------------------------------------//
* 上面这段代码中可以看到,状态机的状态跳转,各状态下的逻辑功能输出,在一个always块中实现。当功能较为复杂时,代码结果臃肿复杂,不利于阅读和维护,以及添加约束条件。
==== 五、 实验步骤及实验结果 ====
- 新建工程,器件型号选择SL2S-25E-8U213C,输入类型选择RTL描述。
- 在“源文件”栏将例程下的源文件添加到工程中,并点击“完成”按钮。
- 也可以跳过添加源文件步骤,自己建立工程文件:在设计管理界面,建立各个模块对应的源文件;通过点击“+”号,将建立的源文件添加到工程中。
- 源文件添加完成后,点击语法检查,检查通过后退出设计管理界面。
- 主界面点击“RTL综合”按钮。如果有报错,通过编译报告查看错误信息并对源文件进行修改。
- 编译通过后点击左侧栏的“物理约束”按钮,绑定引脚信息。如果弹出的“物理约束”界面中出现的端口信号与工程代码中设计的不符,点击左侧栏“工程属性”按钮,查看“顶层模块”一栏是否为工程设计中的顶层模块。
- 点击左侧栏的“全部运行”按钮,进行全编译,生成bit文件。
- 将XiST USB Cable 连接到JTAG口,并给iCore3L核心板供电。
- 点击 “下载/编程”按钮,将生成的bit 文件下载到iCore3L。
- 可以看到iCore3L开发板上LED灯每隔3S改变一次亮灭状态。
==== 六、 拓展实验 ====
* 通过HqInsight采样状态机跳转信号及状态切换,观察FSM的状态跳转及控制条件的变化。