| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801**||| |技术支持邮件|Gingko@vip.163.com||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2020-12-03 | zgf | 初次建立 | ===== 实验十四:有限状态机实验——三段式状态机描述 ===== ==== 一、 实验目的与意义 ==== - 掌握三段式状态机的描述方法。 - 掌握宏定义、参数变量的使用方法。 ==== 二、 实验设备及平台 ==== - iCore3L 双核心板。 - XiST USB CABLE(或相同功能)仿真器。 - Micro USB线缆。 - 装有HqFpga开发平台的电脑一台。 ==== 三、 实验原理 ==== * 三段式状态机由三个always模块实现,其中一个模块采用同步时序的方式描述状态转移,另一个模块采用组合逻辑的方式判断状态转移条件、描述状态转移规律,最后一个模块描述状态输出。 * 三段式与二段式状态机相比,它能够根据状态转移规律,在上一个状态根据输入条件判断当前状态的输出,从而在不插入额外时钟节拍的前提下实现寄存器输出,弥补二段式状态机的不足。 * 本实验的实验原理是通过硬件语言描述产生一个周期为1s的触发信号,以该信号触发状态转移,实现状态跳转,通过状态判断控制led的亮灭。在其中一个always模块采用同步时序描述状态转移,在另一个模块中判断状态转移条件、描述状态转移的规律,在最后一个模块中描述led状态输出。 ==== 四、 代码讲解 ==== * 本实验状态机的主要功能是通过状态切换实现led的闪烁,目的是通过对led状态跳转的控制,学习三段式状态机的原理及代码实现。 * 通过计数器产生一个标志信号state_sig,在状态机中检测到该信号后进行状态跳转;上电复位之后进入state_idle状态,led是灭的;1秒后检测到标志信号state_sig为高后,状态跳转到state_led_on状态,点亮led;当再次检测到state_sig信号为高时,状态跳转到state_led_off状态,led灭;1秒后state_sig信号再次拉高,状态跳转至state_led_on,以此循环实现led的闪烁。其代码如下: //----------------------------------------------------------// //产生状态改变的输入信号 reg state_sig; always@(posedge fpga_clk or negedge rst_n) if(!rst_n) state_sig <=1'b0; else if(time_cnt == 32'd25_000_000) state_sig <= 1'b1; else state_sig <= 1'b0; //----------------------------------------------------------// parameter led_on = 3'b000;// power low led on parameter led_off = 3'b111;// power high led off reg [2:0] led_r; reg [2:0] led_current_state; reg [2:0] led_next_state; //----------------------------------------------------------// //时序逻辑,控制状态跳转 always@(posedge fpga_clk or negedge rst_n) if(!rst_n) led_current_state <= `STATE_IDLE; else led_current_state <= led_next_state; //----------------------------------------------------------// //组合逻辑,控制状态跳转条件及状态输出 always@(led_current_state or state_sig or rst_n) if(!rst_n) led_next_state <= `STATE_IDLE; else case(led_current_state) `STATE_IDLE:begin if(state_sig) led_next_state <= `STATE_LED_ON; else led_next_state <= `STATE_IDLE; end `STATE_LED_ON:begin if(state_sig) led_next_state <= `STATE_LED_OFF; else led_next_state <= `STATE_LED_ON; end `STATE_LED_OFF:begin if(state_sig) led_next_state <= `STATE_LED_ON; else led_next_state <= `STATE_LED_OFF; end default: led_next_state <= `STATE_IDLE; endcase //----------------------------------------------------------// //逻辑输出 always@(posedge fpga_clk or negedge rst_n) if(!rst_n) led_r <= led_off; else case(led_next_state) `STATE_IDLE: led_r <= led_on; `STATE_LED_ON: led_r <= led_off; `STATE_LED_OFF: led_r <= led_on; endcase //----------------------------------------------------------// //led状态输出 assign fpga_led = led_r; ==== 五、 实验步骤及实验结果 ==== 1、 新建工程,器件选择SL2S-25E-8U213C。输入类型选择RTL输入。 2、 通过点击“源文件”栏的“+”,将例程下的源文件添加到工程中;点击“完成”按钮。或者跳过添加源文件,在设计管理界面新建源文件,并添加到工程。 {{ :icore3l:icore3l_fpga_14_1.png?direct |图 14-1 新建工程及添加源文件}} 3、 建立源文件的步骤:点击左侧栏“设计管理”按钮,然后点击“新建文件”按钮,建立状态机模块文件(fsm_ctrl.v)和顶层模块文件(three_fsm.v),并在顶层模块中例化复位控制模块和状态机模块。之后进行语法检查并保存源文件。 * 注意,在左侧栏,通过右键单击选中的源文件,可以将其设置为顶层模块,如下图所示。 {{ :icore3l:icore3l_fpga_14_2.png?direct |图 14-2 可在“设计管理”界面将模块设置为顶层模块}} 4、 点击主界面的“RTL综合”按钮,运行结果无报错后点击左侧栏的“物理约束”按钮,进行引脚绑定。 5、 物理约束添加完成后,进行编译。 6、 将XiST USB Cable 连接到iCore3L的JTAG口,通过Micro USB给板子供电。 7、 将编译生成的bit文件下载到FPGA中。 8、 可以看到iCore3L 上LED灯每1秒切换一次亮灭状态。 ==== 六、 拓展实验 ==== - 通过HqInsight采样状态机跳转信号及状态切换,观察信号变化。 - 观察HqInsight采样信号,分析一段式状态机、二段式状态机和三段式状态机状态跳转的时序有何不同。