*银杏科技有限公司旗下技术文档发布平台  ||||
|技术支持电话|0379-69926675-801**|||
	
		| 技术支持邮件 | Gingko@vip.163.com | 
	
		| 版本 | 日期 | 作者 | 修改内容 | 
	
		| V1.0 | 2020-06-29 | gingko | 初次建立 | 
实验十四:有限状态机实验——二段式状态机描述
一、 实验目的与意义
-  掌握二段式状态机的描述方法。 
-  掌握宏定义、参数变量的使用方法。 
 
二、 实验设备及平台
- 
-  USB CABLE(或相同功能)仿真器。 
-  Micro USB线缆。 
-  ISE开发平台。 
-  电脑一台。 
 
三、 实验原理
-  状态机是一种设计思想,通常由组合逻辑和寄存器两部分组成。寄存器用于存储状态,组合逻辑完成状态译码和产生输出信号。状态机的组成有3各基本要素:状态、输入和输出。其中状态是用来划分逻辑顺序和时序规律的变量;输入指的是状态机进入每个状态的条件;输出指的是在某种状态下发生的事件。 
-  描述状态机关键是要描述清楚状态机的三个要素,即如何进行状态转移、每个状态的输出是什么、状态转移的条件是什么等。在Verilog硬件描述时,状态机有3种常用的描述方法:一段式、二段式和三段式。 
-  二段式状态机的整个功能由两个模块完成,一个always模块采用同步时序的方法描述状态转移,另一个模块采用组合逻辑的方式判断状态转移条件,描述状态转移规律,两者结合功能完成状态机功能。 
-  二段式与一段式状态机相比,将同步时序和组合逻辑分别放在不同的always模块中,不仅便于阅读、理解、维护,更重要的是利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线实现设计。在二段式描述中,常采用组合逻辑描述状态的输出,这种组合逻辑有产生毛刺的可能性,且不利于约束,这也是二段式描述的缺点。 
-  本实验的实验原理是通过硬件语言描述产生一个周期为3s的时间闸门信号,以该信号作为状态转移的触发信号来实现状态跳转,通过状态跳转改变LED的亮灭。在其中一个always模块采用同步时序描述状态转移,在另一个模块中判断状态转移条件、描述状态转移的规律和输出,实现控制LED的状态。 
 
四、 代码讲解
-  本实验状态机的主要功能是通过状态切换实现LED的闪烁控制。 
-  本实验代码按照两段式状态机的控制原理编写的,即一个always模块采用同步时序逻辑的方式控制状态机从当前状态跳转到下一个状态。另一个always模块控制不同状态下的逻辑输出。 
-  本实验中状态机控制LED跳转的原理如下: - 
-  1、通过计数器计数,产生一个每3秒钟拉高一次的闸门信号state_sig; 
-  2、时序逻辑always模块控制状态机由当前状态寄存器切换到到下一个状态寄存器。 
-  3、另一个always模块中,首先判断当前状态寄存器的值,根据寄存器值跳转到相应的状态,并根据闸门信号State_sig判断是否更新状态寄存器的变量。也就是跳转的下一个状态是否和当前状态保持一样。 
-  4、状态机跳转到相应状态时,根据当前状态控制LED的亮灭。 
 
-  在这个两段式状态机中,注意状态更新的always模块是时序逻辑,和clk_25m时钟同步;而控制状态寄存器更新的always模块的触发信号则不同。具体代码如下: 
//控制led亮灭的状态机
//状态机流程,上电复位后进入空闲状态,然后等待大约3s时间闸门打开时进入点亮led状态,当检测到时间
//闸门信号的高电平时,将状态切换至熄灭led状态,再次检测到时间闸门时切换至亮状态,如此循环。
    reg led_r;
    reg [2:0]led_current_state;//当前状态
    reg [2:0]led_next_state;//下一个状态
 
//状态跳转逻辑设计always块
    always@(posedge clk_25m or negedge rst_n)
        begin
            if(!rst_n)
                begin
                    led_current_state <= `state_idle;
                end
            else
                begin
                    led_current_state <= led_next_state;
                end
        end
 
//状态逻辑输出
    always@(led_current_state or state_sig or rst_n)
        begin
            if(!rst_n)
                begin
                    led_r <= led_off;
                    led_next_state <= `state_idle;
                end
            else
                begin
                    case(led_current_state)
                        `state_idle:begin
                            if(state_sig)
                                begin
                                    led_next_state <= `state_led_on;
                                    led_r <= led_on;
                                end
                            else
  				begin
                                    led_next_state <= `state_idle;
                                end
                            end
                        `state_led_on:begin
                            if(state_sig)
                                begin
                                    led_next_state <= `state_led_off;
                                    led_r <= led_off;
                                end
                            else
                                begin
                                    led_next_state <= `state_led_on;
                                end
                            end
                        `state_led_off:begin
                            if(state_sig)
                                begin
                                    led_next_state <= `state_led_on;
                                    led_r <= led_on;
                                end
                            else
                                begin
                                    led_next_state <= `state_led_off;
                                end
                            end
                    endcase
                end
        end
 
五、 实验步骤及实验结果
 
-  将硬件正确连接,如图14-1所示。 
-  将编写好的代码进行编译,并下载到开发板中; 
-  观察实验现象——FPGA_LED闪烁,间隔大约为3s; 
 
六、 拓展实验
-  通过逻辑分析仪采样状态机跳转信号及状态切换,观察信号变化。 
-  对比一段式状态机和二段式状态机状态跳转的时序有何不同。