状态机分为一段式,两段式以及三段式,其分类是根据module块中always语块的个数来区别。这里说的三段式其优势在于清晰容易看出状态机的结构,代码也更容易维护,因此更推荐使用。
模块结构
下图是状态机的结构图
最左边的模块为触发器(具有寄存功能),在Verilog中我们常用异步复位的D触发器,为时序电路,在赋值时使用非阻塞赋值。右边两个模块为组合逻辑的模块,用来描述状态的转移和最终的输出,当然,描述输出的组合逻辑模块也可用时序逻辑来写。
代码模块
第一个always块,描述当前状态的寄存器
always@(posedge clk or negedge rst_n) if(!rst_n) current_state <= idle; else current_state <= next_idle;
第二个always块,描述下一状态
always@(*) case(current_state) idle : if(…) next_state = …; else if(…) next_state = …; st_1 : if(…) next_state = …; else if(…) next_state = …; . . . default : next_state = …; endcase;
第三个always块,描述最后输出
组合逻辑
always@(*) if(!rst_n) output = 0; else begin case(next_state) st_1 : output = …; . . . default : output = …; endcase end
时序逻辑
always@(posedge clk or negedge rst_n)begin if(!rst_n) out<=0; else if(next_state==...) out<=1; else out<=0; end
实例:三段式状态机实现1001序列检测
1.状态转移图
2. 代码
//序列检测1001 module xuliejiance( input data, input clk, input rst_n, output reg out ); parameter idle=0; parameter st_1=1; parameter st_2=2; parameter st_3=3; parameter st_4=4;//对状态转移图中5个状态定义常数 reg[2:0] current_state; reg[2:0] next_state;//5个状态需要3位二进制数 always@(posedge clk or negedge rst_n)begin if(!rst_n) current_state<=idle; else current_state<=next_state; end always@(*)begin case(current_state) idle : if(data==0) next_state = idle; else if(data==1) next_state = st_1; st_1 : if(data==0) next_state = st_2; else if(data==1) next_state = st_1; st_2 : if(data==0) next_state = st_3; else if(data==1) next_state = st_1; st_3 : if(data==0) next_state = idle; else if(data==1) next_state = st_4; st_4 : next_state = idle; default : next_state = idle; endcase end always@(posedge clk or negedge rst_n)begin if(!rst_n) out<=0; else if(next_state==st_4) out<=1; else out<=0; end endmodule
3.仿真
module tb_xuliejiance; // Inputs reg data; reg clk; reg rst_n; // Outputs wire out; // Instantiate the Unit Under Test (UUT) xuliejiance uut ( .data(data), .clk(clk), .rst_n(rst_n), .out(out) ); always #50 clk = ~clk; initial begin // Initialize Inputs data = 0; clk = 1; rst_n = 0; // Wait 100 ns for global reset to finish #201; rst_n = 1; #100; data = 0; #100; data = 1; #100; data = 0; #100; data = 0; #100; data = 0; #100; data = 1; #100; data = 0; #100; data = 0; #100; data = 1; // Add stimulus here end endmodule
波形图