Verilog实现FSM有限状态机
本文使用Verilog搭建一个基础的FSM有限状态机。该FSM仅包含控制模块,无数据链路。
程序要求:
输入:h,reset信号,时钟信号
输出:q
FSM状态转换示意图:
该状态机将在接收到连续的3个h信号“1,0,1”后输出q高电平,其他状态维持低电平。
FSM模块大致可以分为三部分:1. 根据当前状态和输入信号计算下一状态;2. 在时钟信号上升沿更新当前状态,或是在接收到reset信号后重置为初始状态;3. 根据当前状态计算输出信号。
module FSM (input R, h, CLK, output reg q); reg [1:0] next_st, current_st; always @ (*) //next state logic case (current_st) 2'b00: if(h == 1) next_st = 2'b01; else next_st = 2'b00; 2'b01: if(h == 0) next_st = 2'b10; else next_st = 2'b00; 2'b10: if(h == 1) next_st = 2'b11; else next_st = 2'b00; 2'b11: next_st = 2'b00; default: next_st = 2'hX; endcase always @ (posedge CLK, posedge R) if(R) current_st <= 2'b00; else current_st <= next_st; always @ (*) // output logic case (current_st) 2'b11: q = 1; default: q = 0; endcase endmodule
编写一个简单的测试脚本。
module mux4to1_tb(); // Internal connections reg R, h, CLK; wire q; // Instantiate mu0_alu as dut (device under test) FSM dut(R, h, CLK, q); // Test vectors initial begin CLK=0; #100 R=1; h=0; #100 R=0; #100 h=1; #100 h=0; #100 h=1; #100 ; #100 $finish; // end the simulation end always #50 CLK = ~CLK; // Save results as VCD file // Do not change initial begin $dumpfile("FSM_tb_results.vcd"); // Save simulation waveforms in this file $dumpvars; // Capture all simulation waveforms end endmodule
注:该脚本测试用例并不完善,理论上测试应涵盖FSM的所有数据路径。
验证输出波形可以发现输出信号q在输入信号h经历“1,0,1”的变换后在下一个时钟信号上升沿正确切换为高电平输出。